8#ifndef META_OCEAN_CV_FRAME_INTERPOLATOR_BILINEAR_H
9#define META_OCEAN_CV_FRAME_INTERPOLATOR_BILINEAR_H
80 static inline bool resize(
Frame& frame,
const unsigned int width,
const unsigned int height,
Worker* worker =
nullptr);
278 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);
311 template <
typename TScalar = Scalar>
312 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);
332 template <
typename TSource,
typename TTarget,
typename TScalar = Scalar,
typename TIntermediate = TScalar>
333 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));
383 template <
typename T,
unsigned int tChannels>
384 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);
405 template <
typename T,
unsigned int tChannels>
406 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);
424 template <
unsigned int tChannels>
425 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);
454 template <
unsigned int tChannels>
455 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);
478 template <
typename T,
unsigned int tChannels>
479 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);
503 template <
unsigned int tChannels>
504 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);
528 template <
unsigned int tChannels>
529 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);
555 template <
unsigned int tChannels>
556 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);
576 template <
unsigned int tChannels>
577 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);
598 template <
unsigned int tChannels>
599 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);
618 template <
typename T,
unsigned int tChannels>
619 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);
640 template <
unsigned int tChannels>
641 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);
661 template <
typename T,
unsigned int tChannels>
662 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);
678 template <
unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT,
typename TScalar = Scalar>
679 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);
699 template <
typename TSource,
typename TTarget,
unsigned int tChannels, PixelCenter tPixelCenter = PC_TOP_LEFT,
typename TScalar = Scalar,
typename TIntermediate = TScalar>
700 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));
717 template <
unsigned int tChannels,
bool tAlphaAtFront,
bool tTransparentIs0xFF>
718 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);
732 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);
745 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);
769 template <
unsigned int tChannels>
770 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);
789 template <
unsigned int tChannels>
790 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);
808 template <
unsigned int tChannels>
809 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);
835 template <
typename T>
836 static void interpolateRowVertical(
const T* sourceRowTop,
const T* sourceRowBottom, T* targetRow,
const unsigned int elements,
const float factorBottom);
851 template <
typename T,
unsigned int tChannels>
852 static void interpolateRowHorizontal(
const T* extendedSourceRow, T* targetRow,
const unsigned int targetWidth,
const unsigned int channels,
const unsigned int* interpolationLocations,
const float* interpolationFactorsRight);
854#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
879 template <
typename T>
880 static void interpolateRowVerticalNEON(
const T* sourceRowTop,
const T* sourceRowBottom, T* targetRow,
const unsigned int elements,
const float factorBottom);
894 template <
unsigned int tChannels>
910 template <
typename T,
unsigned int tChannels>
911 static void interpolateRowHorizontalNEON(
const T* extendedSourceRow, T* targetRow,
const unsigned int targetWidth,
const unsigned int channels,
const unsigned int* interpolationLocations,
const float* interpolationFactorsRight);
931 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);
953 template <
typename T,
typename TScale,
unsigned int tChannels>
954 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);
972 template <
unsigned int tChannels>
973 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);
1001 template <
unsigned int tChannels>
1002 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);
1023 template <
unsigned int tChannels>
1024 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);
1045 template <
typename T,
unsigned int tChannels>
1046 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);
1048#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1077 template <
unsigned int tChannels>
1078 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);
1099 template <
unsigned int tChannels>
1100 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);
1117 template <
unsigned int tChannels>
1118 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);
1134 template <
unsigned int tChannels>
1135 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);
1139#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1168 template <
unsigned int tChannels>
1169 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);
1190 template <
unsigned int tChannels>
1191 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);
1208 template <
unsigned int tChannels>
1209 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);
1220 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);
1244 template <
unsigned int tChannels>
1245 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);
1265 template <
unsigned int tChannels>
1266 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);
1290 template <
unsigned int tChannels>
1291 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);
1309 template <
unsigned int tChannels>
1310 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);
1329 template <
unsigned int tChannels>
1330 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);
1348 template <
unsigned int tChannels>
1349 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);
1368 template <
typename T,
unsigned int tChannels>
1369 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);
1371#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1389 template <
unsigned int tChannels>
1390 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);
1413 template <
unsigned int tChannels>
1414 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);
1419 ocean_assert(frame.
isValid());
1420 ocean_assert(width >= 1u && height >= 1u);
1424 if (!
resize(frame, target, worker))
1432 frame = std::move(target);
1436template <
typename TScalar>
1439 ocean_assert(frame !=
nullptr);
1440 ocean_assert(channels >= 1u && channels <= 8u);
1447 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<1u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1451 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<2u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1455 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<3u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1459 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<4u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1463 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<5u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1467 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<6u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1471 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<7u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1475 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<8u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1486 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<1u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1490 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<2u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1494 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<3u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1498 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<4u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1502 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<5u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1506 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<6u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1510 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<7u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1514 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<8u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1519 ocean_assert(
false &&
"Invalid channel number");
1523template <
typename TSource,
typename TTarget,
typename TScalar,
typename TIntermediate>
1526 ocean_assert(frame !=
nullptr);
1527 ocean_assert(channels >= 1u && channels <= 8u);
1534 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 1u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1538 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 2u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1542 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 3u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1546 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 4u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1550 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 5u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1554 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 6u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1558 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 7u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1562 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 8u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1573 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 1u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1577 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 2u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1581 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 3u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1585 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 4u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1589 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 5u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1593 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 6u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1597 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 7u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1601 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 8u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1606 ocean_assert(
false &&
"Invalid channel number");
1610template <
typename T,
unsigned int tChannels>
1611inline 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)
1613 ocean_assert(source !=
nullptr && target !=
nullptr);
1614 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
1615 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
1617 const double sourceX_s_targetX = double(sourceWidth) / double(targetWidth);
1618 const double sourceY_s_targetY = double(sourceHeight) / double(targetHeight);
1620 scale<T, tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, worker);
1623template <
typename T,
unsigned int tChannels>
1624inline 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)
1626 ocean_assert(source !=
nullptr && target !=
nullptr);
1627 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
1628 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
1629 ocean_assert(sourceX_s_targetX > 0.0);
1630 ocean_assert(sourceY_s_targetY > 0.0);
1632 if (sourceWidth == targetWidth && sourceHeight == targetHeight)
1634 FrameConverter::subFrame<T>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, 0u, 0u, 0u, 0u, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements);
1638 if (std::is_same<T, uint8_t>::value)
1642 scale8BitPerChannel<tChannels>((
const uint8_t*)source, (uint8_t*)target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, worker);
1650 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);
1654 scaleSubset<T, TScale, tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
1659template <
unsigned int tChannels>
1660inline 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)
1667 if (targetWidth >= 4u)
1669#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1670 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);
1672#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1673 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);
1678 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);
1682 if (targetWidth >= 4u)
1684#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1685 affine8BitPerChannelSSESubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1687#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1688 affine8BitPerChannelNEONSubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1693 affine8BitPerChannelSubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1697template <
unsigned int tChannels>
1698inline 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)
1705 if (outputWidth >= 4u)
1707#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1708 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);
1710#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1711 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);
1716 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);
1720 if (outputWidth >= 4u)
1722#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1723 homography8BitPerChannelSSESubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1725#elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1726 homography8BitPerChannelNEONSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1731 homography8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1735template <
typename T,
unsigned int tChannels>
1736inline 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)
1738 if (std::is_same<T, uint8_t>::value)
1740 homography8BitPerChannel<tChannels>((
const uint8_t*)input, inputWidth, inputHeight, input_H_output, (
const uint8_t*)borderColor, (uint8_t*)output, outputOrigin, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, worker);
1750 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);
1754 homographySubset<T, tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1759template <
unsigned int tChannels>
1760inline 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)
1764 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);
1768 homographies8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, homographies, borderColor, output, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1772template <
unsigned int tChannels>
1773inline 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)
1780 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);
1784 homographyMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, output, outputMask, maskValue, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, outputHeight);
1788template <
unsigned int tChannels>
1789inline 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)
1793 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);
1797 homographiesMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, homographies, output, outputMask, maskValue, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, outputHeight);
1801template <
unsigned int tChannels>
1806 const PinholeCamera::DistortionLookup outputCameraDistortionLookup(outputCamera, 10u);
1810 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographyWithCamera8BitPerChannelSubset<tChannels>, &inputCamera, &outputCamera, &outputCameraDistortionLookup, input, &normalizedHomography, useDistortionParameters, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputCamera.
height());
1814 homographyWithCamera8BitPerChannelSubset<tChannels>(&inputCamera, &outputCamera, &outputCameraDistortionLookup, input, &normalizedHomography, useDistortionParameters, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, outputCamera.
height());
1818template <
unsigned int tChannels>
1819inline 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)
1823 const PinholeCamera::DistortionLookup outputCameraDistortionLookup(outputCamera, 10u);
1827 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);
1831 homographyWithCameraMask8BitPerChannelSubset<tChannels>(&inputCamera, &outputCamera, &outputCameraDistortionLookup, input, inputPaddingElements, &normalizedHomography, output, outputMask, outputPaddingElements, outputMaskPaddingElements, maskValue, 0u, outputCamera.
height());
1835template <
typename T,
unsigned int tChannels>
1836inline 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)
1838 if constexpr (std::is_same<T, uint8_t>::value)
1840#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1841 if ((tChannels >= 1u && input_LT_output.
sizeX() >= 8) || (tChannels >= 2u && input_LT_output.
sizeX() >= 4))
1847 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);
1851 lookup8BitPerChannelSubsetNEON<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1860 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);
1864 lookup8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1869 ocean_assert((!std::is_same<T, uint8_t>::value));
1873 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);
1877 lookupSubset<T, tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1882template <
unsigned int tChannels>
1883inline 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)
1887 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);
1891 lookupMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, output, outputMask, maskValue, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1895template <
typename T,
unsigned int tChannels>
1896void 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)
1898 static_assert(tChannels >= 1u,
"Invalid channel number!");
1900 ocean_assert(sourceFrame !=
nullptr);
1901 ocean_assert(sourceCamera.
isValid());
1903 ocean_assert(targetCamera.
isValid());
1904 ocean_assert(targetFrame !=
nullptr);
1905 ocean_assert(binSizeInPixel >= 1u);
1907 const size_t binsX = std::max(1u, targetCamera.
width() / binSizeInPixel);
1908 const size_t binsY = std::max(1u, targetCamera.
height() / binSizeInPixel);
1911 for (
size_t yBin = 0; yBin <= lookupTable.
binsY(); ++yBin)
1913 for (
size_t xBin = 0; xBin <= lookupTable.
binsX(); ++xBin)
1917 constexpr bool makeUnitVector =
false;
1919 const Vector3 rayI = source_R_target * targetCamera.
vector(cornerPosition, makeUnitVector);
1936 lookup<T, tChannels>(sourceFrame, sourceCamera.
width(), sourceCamera.
height(), lookupTable,
true , borderColor, targetFrame, sourceFramePaddingElements, targetFramePaddingElements, worker);
1938 if (source_OLT_target)
1940 *source_OLT_target = std::move(lookupTable);
1944template <
unsigned int tChannels>
1945void 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)
1947 static_assert(tChannels != 0u,
"Invalid channel number!");
1949 ocean_assert(source !=
nullptr && target !=
nullptr);
1950 ocean_assert(width >= 1u && height >= 1u);
1954 worker->
executeFunction(
Worker::Function::createStatic(&rotate8BitPerChannelSubset<tChannels>, source, target, width, height, horizontalAnchorPosition, verticalAnchorPosition, angle, borderColor, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, height);
1958 rotate8BitPerChannelSubset<tChannels>(source, target, width, height, horizontalAnchorPosition, verticalAnchorPosition, angle, borderColor, sourcePaddingElements, targetPaddingElements, 0u, height);
1962template <
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar>
1965 static_assert(tChannels != 0u,
"Invalid channel number!");
1966 static_assert(tPixelCenter ==
PC_TOP_LEFT || tPixelCenter ==
PC_CENTER,
"Invalid pixel center!");
1968 ocean_assert(frame !=
nullptr && result !=
nullptr);
1969 ocean_assert(width != 0u && height != 0u);
1971 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
1973 ocean_assert(position.
x() >= TScalar(0));
1974 ocean_assert(position.
y() >= TScalar(0));
1978 ocean_assert(position.
x() <= TScalar(width - 1u));
1979 ocean_assert(position.
y() <= TScalar(height - 1u));
1981 const unsigned int left = (
unsigned int)(position.
x());
1982 const unsigned int top = (
unsigned int)(position.
y());
1983 ocean_assert(left < width && top < height);
1985 const TScalar tx = position.
x() - TScalar(left);
1986 ocean_assert(tx >= 0 && tx <= 1);
1987 const unsigned int txi = (
unsigned int)(tx * TScalar(128) + TScalar(0.5));
1988 const unsigned int txi_ = 128u - txi;
1990 const TScalar ty = position.
y() - TScalar(top);
1991 ocean_assert(ty >= 0 && ty <= 1);
1992 const unsigned int tyi = (
unsigned int)(ty * TScalar(128) + TScalar(0.5));
1993 const unsigned int tyi_ = 128u - tyi;
1995 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
1996 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
1998 const uint8_t*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2000 const unsigned int txty = txi * tyi;
2001 const unsigned int txty_ = txi * tyi_;
2002 const unsigned int tx_ty = txi_ * tyi;
2003 const unsigned int tx_ty_ = txi_ * tyi_;
2005 for (
unsigned int n = 0u; n < tChannels; ++n)
2007 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u);
2012 ocean_assert(tPixelCenter ==
PC_CENTER);
2014 ocean_assert(position.
x() <= TScalar(width));
2015 ocean_assert(position.
y() <= TScalar(height));
2017 const TScalar xShifted = std::max(TScalar(0.0), position.
x() - TScalar(0.5));
2018 const TScalar yShifted = std::max(TScalar(0.0), position.
y() - TScalar(0.5));
2020 const unsigned int left = (
unsigned int)(xShifted);
2021 const unsigned int top = (
unsigned int)(yShifted);
2023 ocean_assert(left < width);
2024 ocean_assert(top < height);
2026 const TScalar tx = xShifted - TScalar(left);
2027 const TScalar ty = yShifted - TScalar(top);
2029 ocean_assert(tx >= 0 && tx <= 1);
2030 ocean_assert(ty >= 0 && ty <= 1);
2032 const unsigned int txi = (
unsigned int)(tx * TScalar(128) + TScalar(0.5));
2033 const unsigned int txi_ = 128u - txi;
2035 const unsigned int tyi = (
unsigned int)(ty * TScalar(128) + TScalar(0.5));
2036 const unsigned int tyi_ = 128u - tyi;
2038 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2039 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2041 const uint8_t*
const topLeft = frame + top * frameStrideElements + left * tChannels;
2043 const unsigned int txty = txi * tyi;
2044 const unsigned int txty_ = txi * tyi_;
2045 const unsigned int tx_ty = txi_ * tyi;
2046 const unsigned int tx_ty_ = txi_ * tyi_;
2048 for (
unsigned int n = 0u; n < tChannels; ++n)
2050 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u);
2055template <
typename TSource,
typename TTarget,
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar,
typename TIntermediate>
2058 static_assert(tChannels != 0u,
"Invalid channel number!");
2059 static_assert(tPixelCenter ==
PC_TOP_LEFT || tPixelCenter ==
PC_CENTER,
"Invalid pixel center!");
2061 ocean_assert(frame !=
nullptr && result !=
nullptr);
2062 ocean_assert(width != 0u && height != 0u);
2064 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2066 ocean_assert(position.
x() >= TScalar(0));
2067 ocean_assert(position.
y() >= TScalar(0));
2071 ocean_assert(position.
x() <= TScalar(width - 1u));
2072 ocean_assert(position.
y() <= TScalar(height - 1u));
2074 const unsigned int left = (
unsigned int)(position.
x());
2075 const unsigned int top = (
unsigned int)(position.
y());
2077 const TScalar tx = position.
x() - TScalar(left);
2078 ocean_assert(tx >= 0 && tx <= 1);
2080 const TScalar ty = position.
y() - TScalar(top);
2081 ocean_assert(ty >= 0 && ty <= 1);
2083 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2084 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2086 const TSource*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2088 const TIntermediate txty = TIntermediate(tx) * TIntermediate(ty);
2089 const TIntermediate txty_ = TIntermediate(tx) * (TIntermediate(1) - TIntermediate(ty));
2090 const TIntermediate tx_ty = (TIntermediate(1) - TIntermediate(tx)) * TIntermediate(ty);
2091 const TIntermediate tx_ty_ = (TIntermediate(1) - TIntermediate(tx)) * (TIntermediate(1) - TIntermediate(ty));
2095 for (
unsigned int n = 0u; n < tChannels; ++n)
2097 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);
2102 ocean_assert(tPixelCenter ==
PC_CENTER);
2104 ocean_assert(position.
x() <= TScalar(width));
2105 ocean_assert(position.
y() <= TScalar(height));
2107 const TScalar xShifted = std::max(TScalar(0.0), position.
x() - TScalar(0.5));
2108 const TScalar yShifted = std::max(TScalar(0.0), position.
y() - TScalar(0.5));
2110 const unsigned int left = (
unsigned int)(xShifted);
2111 const unsigned int top = (
unsigned int)(yShifted);
2113 ocean_assert(left < width);
2114 ocean_assert(top < height);
2116 const TScalar tx = xShifted - TScalar(left);
2117 const TScalar ty = yShifted - TScalar(top);
2119 ocean_assert(tx >= 0 && tx <= 1);
2120 ocean_assert(ty >= 0 && ty <= 1);
2122 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2123 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2125 const TSource*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2127 const TIntermediate txty = TIntermediate(tx) * TIntermediate(ty);
2128 const TIntermediate txty_ = TIntermediate(tx) * (TIntermediate(1) - TIntermediate(ty));
2129 const TIntermediate tx_ty = (TIntermediate(1) - TIntermediate(tx)) * TIntermediate(ty);
2130 const TIntermediate tx_ty_ = (TIntermediate(1) - TIntermediate(tx)) * (TIntermediate(1) - TIntermediate(ty));
2134 for (
unsigned int n = 0u; n < tChannels; ++n)
2136 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);
2141template <
unsigned int tChannels,
bool tAlphaAtFront,
bool tTransparentIs0xFF>
2144 static_assert(tChannels != 0u,
"Invalid channel number!");
2146 ocean_assert(frame && result);
2153 for (
unsigned int n = 0u; n < tChannels - 1u; ++n)
2163 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2168 ocean_assert(left >= -1 && left <
int(width));
2169 ocean_assert(top >= -1 && top <
int(height));
2171 if ((
unsigned int)left < width - 1u && (
unsigned int)top < height - 1u)
2175 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
2176 const unsigned int txi_ = 128u - txi;
2178 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
2179 const unsigned int tyi_ = 128u - tyi;
2181 const uint8_t*
const topLeft = frame + top * frameStrideElements + left * tChannels;
2183 const unsigned int txty = txi * tyi;
2184 const unsigned int txty_ = txi * tyi_;
2185 const unsigned int tx_ty = txi_ * tyi;
2186 const unsigned int tx_ty_ = txi_ * tyi_;
2188 for (
unsigned int n = 0u; n < tChannels; ++n)
2190 result[n] = (topLeft[n] * tx_ty_ + topLeft[tChannels + n] * txty_
2191 + topLeft[frameStrideElements + n] * tx_ty + topLeft[frameStrideElements + tChannels + n] * txty + 8192u) >> 14u;
2198 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
2199 const unsigned int txi_ = 128u - txi;
2201 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
2202 const unsigned int tyi_ = 128u - tyi;
2204 const unsigned int rightOffset = (left >= 0 && left + 1u < width) ? tChannels : 0u;
2205 const unsigned int bottomOffset = (top >= 0 && top + 1u < height) ? frameStrideElements : 0u;
2207 ocean_assert(left <
int(width) && top <
int(height));
2208 const uint8_t*
const topLeft = frame + max(0, top) * frameStrideElements + max(0, left) * tChannels;
2210 const unsigned int txty = txi * tyi;
2211 const unsigned int txty_ = txi * tyi_;
2212 const unsigned int tx_ty = txi_ * tyi;
2213 const unsigned int tx_ty_ = txi_ * tyi_;
2217 result[n] = (topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_
2218 + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u;
2230template <
unsigned int tChannels>
2231void 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)
2233 static_assert(tChannels >= 1u,
"Invalid channel number!");
2235 ocean_assert(source !=
nullptr && target !=
nullptr);
2236 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
2237 ocean_assert_and_suppress_unused(targetWidth > 0u && targetHeight > 0u, targetHeight);
2238 ocean_assert(source_A_target);
2241 ocean_assert(firstTargetRow + numberOutputRows <= targetHeight);
2243 const unsigned int targetStrideElements = tChannels * targetWidth + targetPaddingElements;
2245 const Scalar scalarSourceWidth_1 =
Scalar(sourceWidth - 1u);
2246 const Scalar scalarSourceHeight_1 =
Scalar(sourceHeight - 1u);
2250 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2251 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2253 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberOutputRows; ++y)
2255 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
2281 for (
unsigned int x = 0u; x < targetWidth; ++x)
2286 const Scalar debugSourceX = (*source_A_target)[0] *
Scalar(x) + (*source_A_target)[3] *
Scalar(y) + (*source_A_target)[6];
2287 const Scalar debugSourceY = (*source_A_target)[1] *
Scalar(x) + (*source_A_target)[4] *
Scalar(y) + (*source_A_target)[7];
2291 if (sourcePosition.
x() <
Scalar(0) || sourcePosition.
x() > scalarSourceWidth_1 || sourcePosition.
y() <
Scalar(0) || sourcePosition.
y() > scalarSourceHeight_1)
2293 *targetRow = *bColor;
2297 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(source, sourceWidth, sourceHeight, sourcePaddingElements, sourcePosition, (uint8_t*)(targetRow));
2305template <
unsigned int tChannels>
2306void 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)
2308 static_assert(tChannels >= 1u,
"Invalid channel number!");
2310 ocean_assert(input !=
nullptr && output !=
nullptr);
2311 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2312 ocean_assert(outputWidth > 0u && outputHeight > 0u);
2313 ocean_assert(input_H_output !=
nullptr);
2315 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
2317 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2319 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
2320 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
2324 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2325 const PixelType bColor = borderColor ? *(PixelType*)borderColor : *(PixelType*)zeroColor;
2327 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2353 const Scalar X2 = (*input_H_output)(2, 0);
2354 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
2356 PixelType* outputRowPixel = (PixelType*)(output + y * outputStrideElements);
2358 for (
unsigned int x = 0u; x < outputWidth; ++x)
2365 ocean_assert(inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
2368 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
2370 *outputRowPixel = bColor;
2374 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputRowPixel));
2382template <
typename T,
unsigned int tChannels>
2383void 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)
2385 static_assert(tChannels >= 1u,
"Invalid channel number!");
2387 ocean_assert(input !=
nullptr && output !=
nullptr);
2388 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2389 ocean_assert_and_suppress_unused(outputWidth > 0u && outputHeight > 0u, outputHeight);
2390 ocean_assert(input_H_output !=
nullptr);
2392 ocean_assert(firstOutputRow + numberOutputRows <= outputHeight);
2394 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2396 const Scalar scalarInputWidth1 =
Scalar(inputWidth - 1u);
2397 const Scalar scalarInputHeight1 =
Scalar(inputHeight - 1u);
2404 constexpr T zeroColor[tChannels] = {T(0)};
2405 const PixelType*
const bColor = borderColor ? (PixelType*)(borderColor) : (PixelType*)(zeroColor);
2407 constexpr TIntermediate bias = TIntermediate(0);
2409 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2435 const Scalar X2 = (*input_H_output)(2, 0);
2436 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
2438 PixelType* outputRowPixel = (PixelType*)(output + y * outputStrideElements);
2440 for (
unsigned int x = 0u; x < outputWidth; ++x)
2447 ocean_assert((std::is_same<float, Scalar>::value) || inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
2450 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
x() <= scalarInputWidth1 && inputPosition.
y() >=
Scalar(0) && inputPosition.
y() <= scalarInputHeight1)
2452 interpolatePixel<T, T, tChannels, CV::PC_TOP_LEFT, Scalar, TIntermediate>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (T*)(outputRowPixel), bias);
2456 *outputRowPixel = *bColor;
2464#if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
2466template <
unsigned int tChannels>
2467inline 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)
2469 static_assert(tChannels >= 1u,
"Invalid channel number!");
2471 ocean_assert(source && target);
2472 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
2473 ocean_assert(targetWidth >= 4u && targetHeight > 0u);
2474 ocean_assert(source_A_target);
2477 ocean_assert_and_suppress_unused(firstTargetRow + numberTargetRows <= targetHeight, targetHeight);
2479 const unsigned int sourceStrideElements = tChannels * sourceWidth + sourcePaddingElements;
2480 const unsigned int targetStrideElements = tChannels * targetWidth + targetPaddingElements;
2484 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2485 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2487 OCEAN_ALIGN_DATA(16)
unsigned int validPixels[4];
2489 OCEAN_ALIGN_DATA(16)
unsigned int topLeftOffsets[4];
2490 OCEAN_ALIGN_DATA(16)
unsigned int topRightOffsets[4];
2491 OCEAN_ALIGN_DATA(16)
unsigned int bottomLeftOffsets[4];
2492 OCEAN_ALIGN_DATA(16)
unsigned int bottomRightOffsets[4];
2495 const __m128 m128_f_X0 = _mm_set_ps1(
float((*source_A_target)(0, 0)));
2496 const __m128 m128_f_X1 = _mm_set_ps1(
float((*source_A_target)(1, 0)));
2498 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
2500 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
2524 const __m128 m128_f_C0 = _mm_set_ps1(
float((*source_A_target)(0, 1) *
Scalar(y) + (*source_A_target)(0, 2)));
2525 const __m128 m128_f_C1 = _mm_set_ps1(
float((*source_A_target)(1, 1) *
Scalar(y) + (*source_A_target)(1, 2)));
2528 const __m128 m128_f_zero = _mm_setzero_ps();
2531 const __m128i m128_i_channels = _mm_set1_epi32(tChannels);
2534 const __m128i m128_i_sourceStrideElements = _mm_set1_epi32(sourceStrideElements);
2537 const __m128i m128_i_sourceWidth_1 = _mm_set1_epi32(
int(sourceWidth) - 1);
2538 const __m128i m128_i_sourceHeight_1 = _mm_set1_epi32(
int(sourceHeight) - 1);
2541 const __m128 m128_f_sourceWidth_1 = _mm_set_ps1(
float(sourceWidth - 1u));
2542 const __m128 m128_f_sourceHeight_1 = _mm_set_ps1(
float(sourceHeight - 1u));
2544 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
2546 if (x + 4u > targetWidth)
2551 ocean_assert(x >= 4u && targetWidth > 4u);
2552 const unsigned int newX = targetWidth - 4u;
2554 ocean_assert(x > newX);
2555 targetRow -= x - newX;
2560 ocean_assert(!(x + 4u < targetWidth));
2566 const __m128 m128_f_x_0123 = _mm_set_ps(
float(x + 3u),
float(x + 2u),
float(x + 1u),
float(x + 0u));
2569 const __m128 m128_f_sourceX = _mm_add_ps(_mm_mul_ps(m128_f_X0, m128_f_x_0123), m128_f_C0);
2570 const __m128 m128_f_sourceY = _mm_add_ps(_mm_mul_ps(m128_f_X1, m128_f_x_0123), m128_f_C1);
2573 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));
2574 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));
2576 const __m128i m128_i_validPixel = _mm_castps_si128(_mm_and_ps(m128_f_validPixelX, m128_f_validPixelY));
2579 if (_mm_test_all_zeros(m128_i_validPixel, _mm_set1_epi32(0xFFFFFFFF)))
2582 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
2583 _mm_store_si128((__m128i*)debugValidPixels, m128_i_validPixel);
2584 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
2587 targetRow[0] = *bColor;
2588 targetRow[1] = *bColor;
2589 targetRow[2] = *bColor;
2590 targetRow[3] = *bColor;
2598 _mm_store_si128((__m128i*)validPixels, m128_i_validPixel);
2599 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
2603 const __m128 m128_f_tx_floor = _mm_floor_ps(m128_f_sourceX);
2604 const __m128 m128_f_ty_floor = _mm_floor_ps(m128_f_sourceY);
2607 const __m128i m128_i_left = _mm_cvtps_epi32(m128_f_tx_floor);
2608 const __m128i m128_i_top = _mm_cvtps_epi32(m128_f_ty_floor);
2611 const __m128i m128_i_right = _mm_min_epu32(_mm_add_epi32(m128_i_left, _mm_set1_epi32(1)), m128_i_sourceWidth_1);
2612 const __m128i m128_i_bottom = _mm_min_epu32(_mm_add_epi32(m128_i_top, _mm_set1_epi32(1)), m128_i_sourceHeight_1);
2615 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));
2616 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));
2617 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));
2618 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));
2621 _mm_store_si128((__m128i*)topLeftOffsets, m128_i_topLeftOffset);
2622 _mm_store_si128((__m128i*)topRightOffsets, m128_i_topRightOffset);
2623 _mm_store_si128((__m128i*)bottomLeftOffsets, m128_i_bottomLeftOffset);
2624 _mm_store_si128((__m128i*)bottomRightOffsets, m128_i_bottomRightOffset);
2632 __m128 m128_f_tx = _mm_sub_ps(m128_f_sourceX, m128_f_tx_floor);
2633 __m128 m128_f_ty = _mm_sub_ps(m128_f_sourceY, m128_f_ty_floor);
2636 m128_f_tx = _mm_mul_ps(m128_f_tx, _mm_set_ps1(128.0f));
2637 m128_f_ty = _mm_mul_ps(m128_f_ty, _mm_set_ps1(128.0f));
2639 m128_f_tx = _mm_round_ps(m128_f_tx, _MM_FROUND_TO_NEAREST_INT);
2640 m128_f_ty = _mm_round_ps(m128_f_ty, _MM_FROUND_TO_NEAREST_INT);
2642 const __m128i m128_i_tx = _mm_cvtps_epi32(m128_f_tx);
2643 const __m128i m128_i_ty = _mm_cvtps_epi32(m128_f_ty);
2645 interpolate4Pixels8BitPerChannelSSE<tChannels>(source, topLeftOffsets, topRightOffsets, bottomLeftOffsets, bottomRightOffsets, validPixels, *bColor, m128_i_tx, m128_i_ty, targetRow);
2651template <
unsigned int tChannels>
2652inline 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)
2654 static_assert(tChannels >= 1u,
"Invalid channel number!");
2656 ocean_assert(input !=
nullptr && output !=
nullptr);
2657 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2658 ocean_assert(outputWidth >= 4u && outputHeight > 0u);
2659 ocean_assert(input_H_output !=
nullptr);
2661 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
2663 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
2664 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2668 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2669 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2671 OCEAN_ALIGN_DATA(16)
unsigned int validPixels[4];
2673 OCEAN_ALIGN_DATA(16)
unsigned int topLeftOffsets[4];
2674 OCEAN_ALIGN_DATA(16)
unsigned int topRightOffsets[4];
2675 OCEAN_ALIGN_DATA(16)
unsigned int bottomLeftOffsets[4];
2676 OCEAN_ALIGN_DATA(16)
unsigned int bottomRightOffsets[4];
2679 const __m128 m128_f_X0 = _mm_set_ps1(
float((*input_H_output)(0, 0)));
2680 const __m128 m128_f_X1 = _mm_set_ps1(
float((*input_H_output)(1, 0)));
2681 const __m128 m128_f_X2 = _mm_set_ps1(
float((*input_H_output)(2, 0)));
2684 const __m128 m128_f_zero = _mm_setzero_ps();
2687 const __m128i m128_i_channels = _mm_set1_epi32(tChannels);
2690 const __m128i m128_i_inputStrideElements = _mm_set1_epi32(inputStrideElements);
2693 const __m128i m128_i_inputWidth_1 = _mm_set1_epi32(
int(inputWidth) - 1);
2694 const __m128i m128_i_inputHeight_1 = _mm_set1_epi32(
int(inputHeight) - 1);
2697 const __m128 m128_f_inputWidth_1 = _mm_set_ps1(
float(inputWidth - 1u));
2698 const __m128 m128_f_inputHeight_1 = _mm_set_ps1(
float(inputHeight - 1u));
2700 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2702 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
2726 const __m128 m128_f_C0 = _mm_set_ps1(
float((*input_H_output)(0, 1) *
Scalar(y) + (*input_H_output)(0, 2)));
2727 const __m128 m128_f_C1 = _mm_set_ps1(
float((*input_H_output)(1, 1) *
Scalar(y) + (*input_H_output)(1, 2)));
2728 const __m128 m128_f_C2 = _mm_set_ps1(
float((*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2)));
2730 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
2732 if (x + 4u > outputWidth)
2737 ocean_assert(x >= 4u && outputWidth > 4u);
2738 const unsigned int newX = outputWidth - 4u;
2740 ocean_assert(x > newX);
2741 outputPixelData -= x - newX;
2746 ocean_assert(!(x + 4u < outputWidth));
2752 const __m128 m128_f_x_0123 = _mm_set_ps(
float(x + 3u),
float(x + 2u),
float(x + 1u),
float(x + 0u));
2755 const __m128 m128_f_xx = _mm_add_ps(_mm_mul_ps(m128_f_X0, m128_f_x_0123), m128_f_C0);
2756 const __m128 m128_f_yy = _mm_add_ps(_mm_mul_ps(m128_f_X1, m128_f_x_0123), m128_f_C1);
2757 const __m128 m128_f_zz = _mm_add_ps(_mm_mul_ps(m128_f_X2, m128_f_x_0123), m128_f_C2);
2759#ifdef USE_APPROXIMATED_INVERSE_OF_ZZ
2764 const __m128 inv_zz_128 = _mm_rcp_ps(m128_f_zz);
2767 const __m128 m128_f_inputX = _mm_mul_ps(m128_f_xx, inv_zz_128);
2768 const __m128 m128_f_inputY = _mm_mul_ps(m128_f_yy, inv_zz_128);
2773 const __m128 m128_f_inputX = _mm_div_ps(m128_f_xx, m128_f_zz);
2774 const __m128 m128_f_inputY = _mm_div_ps(m128_f_yy, m128_f_zz);
2780 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));
2781 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));
2783 const __m128i m128_i_validPixel = _mm_castps_si128(_mm_and_ps(m128_f_validPixelX, m128_f_validPixelY));
2786 if (_mm_test_all_zeros(m128_i_validPixel, _mm_set1_epi32(0xFFFFFFFF)))
2789 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
2790 _mm_store_si128((__m128i*)debugValidPixels, m128_i_validPixel);
2791 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
2794 outputPixelData[0] = *bColor;
2795 outputPixelData[1] = *bColor;
2796 outputPixelData[2] = *bColor;
2797 outputPixelData[3] = *bColor;
2799 outputPixelData += 4;
2805 _mm_store_si128((__m128i*)validPixels, m128_i_validPixel);
2806 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
2810 const __m128 m128_f_tx_floor = _mm_floor_ps(m128_f_inputX);
2811 const __m128 m128_f_ty_floor = _mm_floor_ps(m128_f_inputY);
2814 const __m128i m128_i_left = _mm_cvtps_epi32(m128_f_tx_floor);
2815 const __m128i m128_i_top = _mm_cvtps_epi32(m128_f_ty_floor);
2818 const __m128i m128_i_right = _mm_min_epu32(_mm_add_epi32(m128_i_left, _mm_set1_epi32(1)), m128_i_inputWidth_1);
2819 const __m128i m128_i_bottom = _mm_min_epu32(_mm_add_epi32(m128_i_top, _mm_set1_epi32(1)), m128_i_inputHeight_1);
2822 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));
2823 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));
2824 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));
2825 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));
2828 _mm_store_si128((__m128i*)topLeftOffsets, m128_i_topLeftOffset);
2829 _mm_store_si128((__m128i*)topRightOffsets, m128_i_topRightOffset);
2830 _mm_store_si128((__m128i*)bottomLeftOffsets, m128_i_bottomLeftOffset);
2831 _mm_store_si128((__m128i*)bottomRightOffsets, m128_i_bottomRightOffset);
2839 __m128 m128_f_tx = _mm_sub_ps(m128_f_inputX, m128_f_tx_floor);
2840 __m128 m128_f_ty = _mm_sub_ps(m128_f_inputY, m128_f_ty_floor);
2843 m128_f_tx = _mm_mul_ps(m128_f_tx, _mm_set_ps1(128.0f));
2844 m128_f_ty = _mm_mul_ps(m128_f_ty, _mm_set_ps1(128.0f));
2846 m128_f_tx = _mm_round_ps(m128_f_tx, _MM_FROUND_TO_NEAREST_INT);
2847 m128_f_ty = _mm_round_ps(m128_f_ty, _MM_FROUND_TO_NEAREST_INT);
2849 const __m128i m128_i_tx = _mm_cvtps_epi32(m128_f_tx);
2850 const __m128i m128_i_ty = _mm_cvtps_epi32(m128_f_ty);
2852 interpolate4Pixels8BitPerChannelSSE<tChannels>(input, topLeftOffsets, topRightOffsets, bottomLeftOffsets, bottomRightOffsets, validPixels, *bColor, m128_i_tx, m128_i_ty, outputPixelData);
2853 outputPixelData += 4;
2859OCEAN_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)
2876 const __m128i mask32_Channel0 =
SSE::set128i(0xFFFFFF09FFFFFF06ull, 0xFFFFFF03FFFFFF00ull);
2877 const __m128i mask32_Channel1 =
SSE::set128i(0xFFFFFF0AFFFFFF07ull, 0xFFFFFF04FFFFFF01ull);
2878 const __m128i mask32_Channel2 =
SSE::set128i(0xFFFFFF0BFFFFFF08ull, 0xFFFFFF05FFFFFF02ull);
2886 __m128i multiplication_channel0 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel0));
2889 __m128i multiplication_channel1 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel1));
2892 __m128i multiplication_channel2 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel2));
2896 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel0)));
2897 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel1)));
2898 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel2)));
2902 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel0)));
2903 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel1)));
2904 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel2)));
2908 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel0)));
2909 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel1)));
2910 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel2)));
2913 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
2922 __m128i interpolation_channel0 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel0, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFFFF0CFFull, 0xFF08FFFF04FFFF00ull));
2928 __m128i interpolation_channel1 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel1, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFF0CFFFFull, 0x08FFFF04FFFF00FFull));
2934 __m128i interpolation_channel2 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel2, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFF0CFFFF08ull, 0xFFFF04FFFF00FFFFull));
2939 return _mm_or_si128(_mm_or_si128(interpolation_channel0, interpolation_channel1), interpolation_channel2);
2943OCEAN_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)
2960 const __m128i mask32_Channel0 =
SSE::set128i(0xA0A0A00CA0A0A008ull, 0xA0A0A004A0A0A000ull);
2961 const __m128i mask32_Channel1 =
SSE::set128i(0xA0A0A00DA0A0A009ull, 0xA0A0A005A0A0A001ull);
2962 const __m128i mask32_Channel2 =
SSE::set128i(0xA0A0A00EA0A0A00Aull, 0xA0A0A006A0A0A002ull);
2963 const __m128i mask32_Channel3 =
SSE::set128i(0xA0A0A00FA0A0A00Bull, 0xA0A0A007A0A0A003ull);
2971 __m128i multiplication_channel0 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel0));
2974 __m128i multiplication_channel1 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel1));
2977 __m128i multiplication_channel2 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel2));
2980 __m128i multiplication_channel3 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel3));
2984 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel0)));
2985 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel1)));
2986 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel2)));
2987 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel3)));
2991 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel0)));
2992 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel1)));
2993 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel2)));
2994 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel3)));
2998 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel0)));
2999 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel1)));
3000 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel2)));
3001 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel3)));
3004 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
3011 __m128i interpolation_channel0 = _mm_srli_epi32(_mm_add_epi32(multiplication_channel0, m128_i_8192), 14);
3016 __m128i interpolation_channel1 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel1, m128_i_8192), 14), 8);
3020 __m128i interpolation_channel2 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel2, m128_i_8192), 14), 16);
3024 __m128i interpolation_channel3 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel3, m128_i_8192), 14), 24);
3029 return _mm_or_si128(_mm_or_si128(interpolation_channel0, interpolation_channel1), _mm_or_si128(interpolation_channel2, interpolation_channel3));
3032#ifdef OCEAN_COMPILER_MSC
3038OCEAN_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)
3040 ocean_assert(source !=
nullptr);
3041 ocean_assert(targetPositionPixels !=
nullptr);
3047 OCEAN_ALIGN_DATA(16) PixelType pixels[16];
3051 for (
unsigned int i = 0u; i < 4u; ++i)
3055 pixels[i * 4u + 0u] = *((PixelType*)(source + offsetsTopLeft[i]));
3056 pixels[i * 4u + 1u] = *((PixelType*)(source + offsetsTopRight[i]));
3057 pixels[i * 4u + 2u] = *((PixelType*)(source + offsetsBottomLeft[i]));
3058 pixels[i * 4u + 3u] = *((PixelType*)(source + offsetsBottomRight[i]));
3062 pixels[i * 4u + 0u] = borderColor;
3063 pixels[i * 4u + 1u] = borderColor;
3064 pixels[i * 4u + 2u] = borderColor;
3065 pixels[i * 4u + 3u] = borderColor;
3069 static_assert(
sizeof(__m128i) ==
sizeof(pixels),
"Invalid data type!");
3071 const __m128i m128_pixels = _mm_load_si128((
const __m128i*)pixels);
3077 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3078 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3083 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3084 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3085 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3086 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3102 const __m128i mask32_topLeft =
SSE::set128i(0xFFFFFF0CFFFFFF08ull, 0xFFFFFF04FFFFFF00ull);
3103 const __m128i mask32_topRight =
SSE::set128i(0xFFFFFF0DFFFFFF09ull, 0xFFFFFF05FFFFFF01ull);
3104 const __m128i mask32_bottomLeft =
SSE::set128i(0xFFFFFF0EFFFFFF0Aull, 0xFFFFFF06FFFFFF02ull);
3105 const __m128i mask32_bottomRight =
SSE::set128i(0xFFFFFF0FFFFFFF0Bull, 0xFFFFFF07FFFFFF03ull);
3113 __m128i multiplicationA = _mm_mullo_epi32(m128_factorsTopLeft, _mm_shuffle_epi8(m128_pixels, mask32_topLeft));
3114 __m128i multiplicationB = _mm_mullo_epi32(m128_factorsTopRight, _mm_shuffle_epi8(m128_pixels, mask32_topRight));
3116 multiplicationA = _mm_add_epi32(multiplicationA, _mm_mullo_epi32(m128_factorsBottomLeft, _mm_shuffle_epi8(m128_pixels, mask32_bottomLeft)));
3117 multiplicationB = _mm_add_epi32(multiplicationB, _mm_mullo_epi32(m128_factorsBottomRight, _mm_shuffle_epi8(m128_pixels, mask32_bottomRight)));
3119 __m128i multiplication = _mm_add_epi32(multiplicationA, multiplicationB);
3121 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
3126 const __m128i result = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF0C080400ull));
3128 *((
unsigned int*)targetPositionPixels) = _mm_extract_epi32(result, 0);
3132OCEAN_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)
3134 ocean_assert(source !=
nullptr);
3135 ocean_assert(targetPositionPixels !=
nullptr);
3141 OCEAN_ALIGN_DATA(16) PixelType topLeftPixels[6];
3142 OCEAN_ALIGN_DATA(16) PixelType topRightPixels[6];
3143 OCEAN_ALIGN_DATA(16) PixelType bottomLeftPixels[6];
3144 OCEAN_ALIGN_DATA(16) PixelType bottomRightPixels[6];
3148 for (
unsigned int i = 0u; i < 4u; ++i)
3152 topLeftPixels[i] = *((PixelType*)(source + offsetsTopLeft[i]));
3153 topRightPixels[i] = *((PixelType*)(source + offsetsTopRight[i]));
3154 bottomLeftPixels[i] = *((PixelType*)(source + offsetsBottomLeft[i]));
3155 bottomRightPixels[i] = *((PixelType*)(source + offsetsBottomRight[i]));
3159 topLeftPixels[i] = borderColor;
3160 topRightPixels[i] = borderColor;
3161 bottomLeftPixels[i] = borderColor;
3162 bottomRightPixels[i] = borderColor;
3166 static_assert(
sizeof(__m128i) <=
sizeof(topLeftPixels),
"Invalid data type!");
3168 const __m128i m128_topLeftPixels = _mm_load_si128((
const __m128i*)topLeftPixels);
3169 const __m128i m128_topRightPixels = _mm_load_si128((
const __m128i*)topRightPixels);
3170 const __m128i m128_bottomLeftPixels = _mm_load_si128((
const __m128i*)bottomLeftPixels);
3171 const __m128i m128_bottomRightPixels = _mm_load_si128((
const __m128i*)bottomRightPixels);
3177 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3178 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3183 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3184 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3185 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3186 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3189 const __m128i m128_interpolationResult = interpolate4Pixels8BitPerChannelSSE<3u>(m128_topLeftPixels, m128_topRightPixels, m128_bottomLeftPixels, m128_bottomRightPixels, m128_factorsTopLeft, m128_factorsTopRight, m128_factorsBottomLeft, m128_factorsBottomRight);
3192 memcpy(targetPositionPixels, &m128_interpolationResult, 12u);
3198OCEAN_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)
3200 ocean_assert(source !=
nullptr);
3201 ocean_assert(targetPositionPixels !=
nullptr);
3207 OCEAN_ALIGN_DATA(16) PixelType topLeftPixels[4];
3208 OCEAN_ALIGN_DATA(16) PixelType topRightPixels[4];
3209 OCEAN_ALIGN_DATA(16) PixelType bottomLeftPixels[4];
3210 OCEAN_ALIGN_DATA(16) PixelType bottomRightPixels[4];
3215 for (
unsigned int i = 0u; i < 4u; ++i)
3219 topLeftPixels[i] = *((PixelType*)(source + offsetsTopLeft[i]));
3220 topRightPixels[i] = *((PixelType*)(source + offsetsTopRight[i]));
3221 bottomLeftPixels[i] = *((PixelType*)(source + offsetsBottomLeft[i]));
3222 bottomRightPixels[i] = *((PixelType*)(source + offsetsBottomRight[i]));
3226 topLeftPixels[i] = borderColor;
3227 topRightPixels[i] = borderColor;
3228 bottomLeftPixels[i] = borderColor;
3229 bottomRightPixels[i] = borderColor;
3233 static_assert(
sizeof(__m128i) ==
sizeof(topLeftPixels),
"Invalid data type!");
3235 const __m128i m128_topLeftPixels = _mm_load_si128((
const __m128i*)topLeftPixels);
3236 const __m128i m128_topRightPixels = _mm_load_si128((
const __m128i*)topRightPixels);
3237 const __m128i m128_bottomLeftPixels = _mm_load_si128((
const __m128i*)bottomLeftPixels);
3238 const __m128i m128_bottomRightPixels = _mm_load_si128((
const __m128i*)bottomRightPixels);
3244 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3245 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3250 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3251 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3252 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3253 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3256 const __m128i m128_interpolationResult = interpolate4Pixels8BitPerChannelSSE<4u>(m128_topLeftPixels, m128_topRightPixels, m128_bottomLeftPixels, m128_bottomRightPixels, m128_factorsTopLeft, m128_factorsTopRight, m128_factorsBottomLeft, m128_factorsBottomRight);
3258 _mm_storeu_si128((__m128i*)targetPositionPixels, m128_interpolationResult);
3261template <
unsigned int tChannels>
3262OCEAN_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)
3264 ocean_assert(source !=
nullptr);
3265 ocean_assert(targetPositionPixels !=
nullptr);
3269 OCEAN_ALIGN_DATA(16)
unsigned int factorsTopLeft[4];
3270 OCEAN_ALIGN_DATA(16)
unsigned int factorsTopRight[4];
3271 OCEAN_ALIGN_DATA(16)
unsigned int factorsBottomLeft[4];
3272 OCEAN_ALIGN_DATA(16)
unsigned int factorsBottomRight[4];
3278 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3279 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3284 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3285 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3286 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3287 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3291 _mm_store_si128((__m128i*)factorsTopLeft, m128_factorsTopLeft);
3292 _mm_store_si128((__m128i*)factorsTopRight, m128_factorsTopRight);
3293 _mm_store_si128((__m128i*)factorsBottomLeft, m128_factorsBottomLeft);
3294 _mm_store_si128((__m128i*)factorsBottomRight, m128_factorsBottomRight);
3296 for (
unsigned int i = 0u; i < 4u; ++i)
3300 const uint8_t* topLeft = source + offsetsTopLeft[i];
3301 const uint8_t* topRight = source + offsetsTopRight[i];
3303 const uint8_t* bottomLeft = source + offsetsBottomLeft[i];
3304 const uint8_t* bottomRight = source + offsetsBottomRight[i];
3306 const unsigned int& factorTopLeft = factorsTopLeft[i];
3307 const unsigned int& factorTopRight = factorsTopRight[i];
3308 const unsigned int& factorBottomLeft = factorsBottomLeft[i];
3309 const unsigned int& factorBottomRight = factorsBottomRight[i];
3311 for (
unsigned int n = 0u; n < tChannels; ++n)
3313 ((uint8_t*)targetPositionPixels)[n] = (uint8_t)((topLeft[n] * factorTopLeft + topRight[n] * factorTopRight + bottomLeft[n] * factorBottomLeft + bottomRight[n] * factorBottomRight + 8192u) >> 14u);
3318 *targetPositionPixels = borderColor;
3321 targetPositionPixels++;
3327#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
3329template <
unsigned int tChannels>
3330void 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)
3332 static_assert(tChannels >= 1u,
"Invalid channel number!");
3334 ocean_assert(source && target);
3335 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
3336 ocean_assert(targetWidth >= 4u && targetHeight > 0u);
3337 ocean_assert(source_A_target);
3340 ocean_assert(firstTargetRow + numberTargetRows <= targetHeight);
3342 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
3343 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
3347 uint8_t zeroColor[tChannels] = {uint8_t(0)};
3348 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
3350 unsigned int validPixels[4];
3352 unsigned int topLeftOffsetsElements[4];
3353 unsigned int topRightOffsetsElements[4];
3354 unsigned int bottomLeftOffsetsElements[4];
3355 unsigned int bottomRightOffsetsElements[4];
3357 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
3360 const float32x4_t m128_f_X0 = vdupq_n_f32(
float((*source_A_target)(0, 0)));
3361 const float32x4_t m128_f_X1 = vdupq_n_f32(
float((*source_A_target)(1, 0)));
3363 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
3365 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
3389 const float32x4_t m128_f_C0 = vdupq_n_f32(
float((*source_A_target)(0, 1) *
Scalar(y) + (*source_A_target)(0, 2)));
3390 const float32x4_t m128_f_C1 = vdupq_n_f32(
float((*source_A_target)(1, 1) *
Scalar(y) + (*source_A_target)(1, 2)));
3393 const float32x4_t m128_f_zero = vdupq_n_f32(0.0f);
3396 const uint32x4_t m128_u_sourceStrideElements = vdupq_n_u32(sourceStrideElements);
3399 const uint32x4_t m128_u_sourceWidth_1 = vdupq_n_u32(sourceWidth - 1u);
3400 const uint32x4_t m128_u_sourceHeight_1 = vdupq_n_u32(sourceHeight - 1u);
3403 const float32x4_t m128_f_sourceWidth_1 = vdupq_n_f32(
float(sourceWidth - 1u));
3404 const float32x4_t m128_f_sourceHeight_1 = vdupq_n_f32(
float(sourceHeight - 1u));
3406 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
3408 if (x + 4u > targetWidth)
3413 ocean_assert(x >= 4u && targetWidth > 4u);
3414 const unsigned int newX = targetWidth - 4u;
3416 ocean_assert(x > newX);
3417 targetRow -= x - newX;
3422 ocean_assert(!(x + 4u < targetWidth));
3428 float x_0123[4] = {float(x + 0u), float(x + 1u), float(x + 2u), float(x + 3u)};
3429 const float32x4_t m128_f_x_0123 = vld1q_f32(x_0123);
3432 const float32x4_t m128_f_sourceX = vmlaq_f32(m128_f_C0, m128_f_X0, m128_f_x_0123);
3433 const float32x4_t m128_f_sourceY = vmlaq_f32(m128_f_C1, m128_f_X1, m128_f_x_0123);
3437 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));
3438 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));
3440 const uint32x4_t m128_u_validPixel = vandq_u32(m128_u_validPixelX, m128_u_validPixelY);
3444 const uint32x2_t m64_u_validPixel = vorr_u32(vget_low_u32(m128_u_validPixel), vget_high_u32(m128_u_validPixel));
3445 if ((vget_lane_u32(m64_u_validPixel, 0) | vget_lane_u32(m64_u_validPixel, 1)) == 0x00000000u)
3448 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
3449 vst1q_u32(debugValidPixels, m128_u_validPixel);
3450 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
3453 targetRow[0] = *bColor;
3454 targetRow[1] = *bColor;
3455 targetRow[2] = *bColor;
3456 targetRow[3] = *bColor;
3465 vst1q_u32(validPixels, m128_u_validPixel);
3466 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
3471 const uint32x4_t m128_u_left = vcvtq_u32_f32(m128_f_sourceX);
3472 const uint32x4_t m128_u_top = vcvtq_u32_f32(m128_f_sourceY);
3475 const uint32x4_t m128_u_right = vminq_u32(vaddq_u32(m128_u_left, vdupq_n_u32(1u)), m128_u_sourceWidth_1);
3476 const uint32x4_t m128_u_bottom = vminq_u32(vaddq_u32(m128_u_top, vdupq_n_u32(1u)), m128_u_sourceHeight_1);
3479 const uint32x4_t m128_u_topLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_top, m128_u_sourceStrideElements);
3480 const uint32x4_t m128_u_topRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_top, m128_u_sourceStrideElements);
3481 const uint32x4_t m128_u_bottomLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_bottom, m128_u_sourceStrideElements);
3482 const uint32x4_t m128_u_bottomRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_bottom, m128_u_sourceStrideElements);
3485 vst1q_u32(topLeftOffsetsElements, m128_u_topLeftOffsetElements);
3486 vst1q_u32(topRightOffsetsElements, m128_u_topRightOffsetElements);
3487 vst1q_u32(bottomLeftOffsetsElements, m128_u_bottomLeftOffsetElements);
3488 vst1q_u32(bottomRightOffsetsElements, m128_u_bottomRightOffsetElements);
3494 float32x4_t m128_f_tx = vsubq_f32(m128_f_sourceX, vcvtq_f32_u32(m128_u_left));
3495 float32x4_t m128_f_ty = vsubq_f32(m128_f_sourceY, vcvtq_f32_u32(m128_u_top));
3498 m128_f_tx = vmulq_f32(m128_f_tx, vdupq_n_f32(128.0f));
3499 m128_f_ty = vmulq_f32(m128_f_ty, vdupq_n_f32(128.0f));
3501 const uint32x4_t m128_u_tx = vcvtq_u32_f32(vaddq_f32(m128_f_tx, vdupq_n_f32(0.5)));
3502 const uint32x4_t m128_u_ty = vcvtq_u32_f32(vaddq_f32(m128_f_ty, vdupq_n_f32(0.5)));
3504 if constexpr (tChannels > 4u)
3514 const uint32x4_t m128_u_tx_ = vsubq_u32(vdupq_n_u32(128u), m128_u_tx);
3515 const uint32x4_t m128_u_ty_ = vsubq_u32(vdupq_n_u32(128u), m128_u_ty);
3519 const uint32x4_t m128_u_tx_ty_ = vmulq_u32(m128_u_tx_, m128_u_ty_);
3520 const uint32x4_t m128_u_txty_ = vmulq_u32(m128_u_tx, m128_u_ty_);
3521 const uint32x4_t m128_u_tx_ty = vmulq_u32(m128_u_tx_, m128_u_ty);
3522 const uint32x4_t m128_u_txty = vmulq_u32(m128_u_tx, m128_u_ty);
3524 unsigned int tx_ty_s[4];
3525 unsigned int txty_s[4];
3526 unsigned int tx_tys[4];
3527 unsigned int txtys[4];
3530 vst1q_u32(tx_ty_s, m128_u_tx_ty_);
3531 vst1q_u32(txty_s, m128_u_txty_);
3532 vst1q_u32(tx_tys, m128_u_tx_ty);
3533 vst1q_u32(txtys, m128_u_txty);
3535 for (
unsigned int i = 0u; i < 4u; ++i)
3539 ocean_assert(topLeftOffsetsElements[i] < sourceStrideElements * sourceHeight);
3540 ocean_assert(topRightOffsetsElements[i] < sourceStrideElements * sourceHeight);
3541 ocean_assert(bottomLeftOffsetsElements[i] < sourceStrideElements * sourceHeight);
3542 ocean_assert(bottomRightOffsetsElements[i] < sourceStrideElements * sourceHeight);
3544 const uint8_t* topLeft = source + topLeftOffsetsElements[i];
3545 const uint8_t* topRight = source + topRightOffsetsElements[i];
3547 const uint8_t* bottomLeft = source + bottomLeftOffsetsElements[i];
3548 const uint8_t* bottomRight = source + bottomRightOffsetsElements[i];
3550 const unsigned int tx_ty_ = tx_ty_s[i];
3551 const unsigned int txty_ = txty_s[i];
3552 const unsigned int tx_ty = tx_tys[i];
3553 const unsigned int txty = txtys[i];
3555 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
3557 for (
unsigned int n = 0u; n < tChannels; ++n)
3559 ((uint8_t*)targetRow)[n] = uint8_t((topLeft[n] * tx_ty_ + topRight[n] * txty_ + bottomLeft[n] * tx_ty + bottomRight[n] * txty + 8192u) >> 14u);
3564 *targetRow = *bColor;
3572 interpolate4Pixels8BitPerChannelNEON<tChannels>(source, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, m128_u_tx, m128_u_ty, targetRow);
3579template <
unsigned int tChannels>
3580void 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)
3582 static_assert(tChannels >= 1u,
"Invalid channel number!");
3584 ocean_assert(input !=
nullptr && output !=
nullptr);
3585 ocean_assert(inputWidth > 0u && inputHeight > 0u);
3586 ocean_assert(outputWidth >= 4u && outputHeight > 0u);
3587 ocean_assert(input_H_output !=
nullptr);
3589 ocean_assert(firstOutputRow + numberOutputRows <= outputHeight);
3591 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
3592 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
3596 uint8_t zeroColor[tChannels] = {uint8_t(0)};
3597 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
3599 unsigned int validPixels[4];
3601 unsigned int topLeftOffsetsElements[4];
3602 unsigned int topRightOffsetsElements[4];
3603 unsigned int bottomLeftOffsetsElements[4];
3604 unsigned int bottomRightOffsetsElements[4];
3606 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
3609 const float32x4_t m128_f_X0 = vdupq_n_f32(
float((*input_H_output)(0, 0)));
3610 const float32x4_t m128_f_X1 = vdupq_n_f32(
float((*input_H_output)(1, 0)));
3611 const float32x4_t m128_f_X2 = vdupq_n_f32(
float((*input_H_output)(2, 0)));
3613 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
3615 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
3639 const float32x4_t m128_f_C0 = vdupq_n_f32(
float((*input_H_output)(0, 1) *
Scalar(y) + (*input_H_output)(0, 2)));
3640 const float32x4_t m128_f_C1 = vdupq_n_f32(
float((*input_H_output)(1, 1) *
Scalar(y) + (*input_H_output)(1, 2)));
3641 const float32x4_t m128_f_C2 = vdupq_n_f32(
float((*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2)));
3644 const float32x4_t m128_f_zero = vdupq_n_f32(0.0f);
3647 const uint32x4_t m128_u_inputStrideElements = vdupq_n_u32(inputStrideElements);
3650 const uint32x4_t m128_u_inputWidth_1 = vdupq_n_u32(inputWidth - 1u);
3651 const uint32x4_t m128_u_inputHeight_1 = vdupq_n_u32(inputHeight - 1u);
3654 const float32x4_t m128_f_inputWidth_1 = vdupq_n_f32(
float(inputWidth - 1u));
3655 const float32x4_t m128_f_inputHeight_1 = vdupq_n_f32(
float(inputHeight - 1u));
3657 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
3659 if (x + 4u > outputWidth)
3664 ocean_assert(x >= 4u && outputWidth > 4u);
3665 const unsigned int newX = outputWidth - 4u;
3667 ocean_assert(x > newX);
3668 outputPixelData -= x - newX;
3673 ocean_assert(!(x + 4u < outputWidth));
3679 float x_0123[4] = {float(x + 0u), float(x + 1u), float(x + 2u), float(x + 3u)};
3680 const float32x4_t m128_f_x_0123 = vld1q_f32(x_0123);
3683 const float32x4_t m128_f_xx = vmlaq_f32(m128_f_C0, m128_f_X0, m128_f_x_0123);
3684 const float32x4_t m128_f_yy = vmlaq_f32(m128_f_C1, m128_f_X1, m128_f_x_0123);
3685 const float32x4_t m128_f_zz = vmlaq_f32(m128_f_C2, m128_f_X2, m128_f_x_0123);
3687#ifdef USE_DIVISION_ARM64_ARCHITECTURE
3690 const float32x4_t m128_f_inputX = vdivq_f32(m128_f_xx, m128_f_zz);
3691 const float32x4_t m128_f_inputY = vdivq_f32(m128_f_yy, m128_f_zz);
3697 float32x4_t inv_zz_128 = vrecpeq_f32(m128_f_zz);
3698 inv_zz_128 = vmulq_f32(vrecpsq_f32(m128_f_zz, inv_zz_128), inv_zz_128);
3701 const float32x4_t m128_f_inputX = vmulq_f32(m128_f_xx, inv_zz_128);
3702 const float32x4_t m128_f_inputY = vmulq_f32(m128_f_yy, inv_zz_128);
3708 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));
3709 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));
3711 const uint32x4_t m128_u_validPixel = vandq_u32(m128_u_validPixelX, m128_u_validPixelY);
3715 const uint32x2_t m64_u_validPixel = vorr_u32(vget_low_u32(m128_u_validPixel), vget_high_u32(m128_u_validPixel));
3716 if ((vget_lane_u32(m64_u_validPixel, 0) | vget_lane_u32(m64_u_validPixel, 1)) == 0x00000000u)
3719 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
3720 vst1q_u32(debugValidPixels, m128_u_validPixel);
3721 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
3724 outputPixelData[0] = *bColor;
3725 outputPixelData[1] = *bColor;
3726 outputPixelData[2] = *bColor;
3727 outputPixelData[3] = *bColor;
3729 outputPixelData += 4;
3736 vst1q_u32(validPixels, m128_u_validPixel);
3737 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
3742 const uint32x4_t m128_u_left = vcvtq_u32_f32(m128_f_inputX);
3743 const uint32x4_t m128_u_top = vcvtq_u32_f32(m128_f_inputY);
3746 const uint32x4_t m128_u_right = vminq_u32(vaddq_u32(m128_u_left, vdupq_n_u32(1u)), m128_u_inputWidth_1);
3747 const uint32x4_t m128_u_bottom = vminq_u32(vaddq_u32(m128_u_top, vdupq_n_u32(1u)), m128_u_inputHeight_1);
3750 const uint32x4_t m128_u_topLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_top, m128_u_inputStrideElements);
3751 const uint32x4_t m128_u_topRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_top, m128_u_inputStrideElements);
3752 const uint32x4_t m128_u_bottomLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_bottom, m128_u_inputStrideElements);
3753 const uint32x4_t m128_u_bottomRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_bottom, m128_u_inputStrideElements);
3756 vst1q_u32(topLeftOffsetsElements, m128_u_topLeftOffsetElements);
3757 vst1q_u32(topRightOffsetsElements, m128_u_topRightOffsetElements);
3758 vst1q_u32(bottomLeftOffsetsElements, m128_u_bottomLeftOffsetElements);
3759 vst1q_u32(bottomRightOffsetsElements, m128_u_bottomRightOffsetElements);
3765 float32x4_t m128_f_tx = vsubq_f32(m128_f_inputX, vcvtq_f32_u32(m128_u_left));
3766 float32x4_t m128_f_ty = vsubq_f32(m128_f_inputY, vcvtq_f32_u32(m128_u_top));
3769 m128_f_tx = vmulq_f32(m128_f_tx, vdupq_n_f32(128.0f));
3770 m128_f_ty = vmulq_f32(m128_f_ty, vdupq_n_f32(128.0f));
3772 const uint32x4_t m128_u_tx = vcvtq_u32_f32(vaddq_f32(m128_f_tx, vdupq_n_f32(0.5)));
3773 const uint32x4_t m128_u_ty = vcvtq_u32_f32(vaddq_f32(m128_f_ty, vdupq_n_f32(0.5)));
3775 if constexpr (tChannels > 4u)
3785 const uint32x4_t m128_u_tx_ = vsubq_u32(vdupq_n_u32(128u), m128_u_tx);
3786 const uint32x4_t m128_u_ty_ = vsubq_u32(vdupq_n_u32(128u), m128_u_ty);
3790 const uint32x4_t m128_u_tx_ty_ = vmulq_u32(m128_u_tx_, m128_u_ty_);
3791 const uint32x4_t m128_u_txty_ = vmulq_u32(m128_u_tx, m128_u_ty_);
3792 const uint32x4_t m128_u_tx_ty = vmulq_u32(m128_u_tx_, m128_u_ty);
3793 const uint32x4_t m128_u_txty = vmulq_u32(m128_u_tx, m128_u_ty);
3795 unsigned int tx_ty_s[4];
3796 unsigned int txty_s[4];
3797 unsigned int tx_tys[4];
3798 unsigned int txtys[4];
3801 vst1q_u32(tx_ty_s, m128_u_tx_ty_);
3802 vst1q_u32(txty_s, m128_u_txty_);
3803 vst1q_u32(tx_tys, m128_u_tx_ty);
3804 vst1q_u32(txtys, m128_u_txty);
3806 for (
unsigned int i = 0u; i < 4u; ++i)
3810 ocean_assert(topLeftOffsetsElements[i] < inputStrideElements * inputHeight);
3811 ocean_assert(topRightOffsetsElements[i] < inputStrideElements * inputHeight);
3812 ocean_assert(bottomLeftOffsetsElements[i] < inputStrideElements * inputHeight);
3813 ocean_assert(bottomRightOffsetsElements[i] < inputStrideElements * inputHeight);
3815 const uint8_t* topLeft = input + topLeftOffsetsElements[i];
3816 const uint8_t* topRight = input + topRightOffsetsElements[i];
3818 const uint8_t* bottomLeft = input + bottomLeftOffsetsElements[i];
3819 const uint8_t* bottomRight = input + bottomRightOffsetsElements[i];
3821 const unsigned int tx_ty_ = tx_ty_s[i];
3822 const unsigned int txty_ = txty_s[i];
3823 const unsigned int tx_ty = tx_tys[i];
3824 const unsigned int txty = txtys[i];
3826 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
3828 for (
unsigned int n = 0u; n < tChannels; ++n)
3830 ((uint8_t*)outputPixelData)[n] = uint8_t((topLeft[n] * tx_ty_ + topRight[n] * txty_ + bottomLeft[n] * tx_ty + bottomRight[n] * txty + 8192u) >> 14u);
3835 *outputPixelData = *bColor;
3843 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, m128_u_tx, m128_u_ty, outputPixelData);
3844 outputPixelData += 4;
3851OCEAN_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)
3853 ocean_assert(source !=
nullptr);
3854 ocean_assert(targetPositionPixels !=
nullptr);
3866 for (
unsigned int i = 0u; i < 4u; ++i)
3877 pixels[i * 4u + 0u] = borderColor;
3878 pixels[i * 4u + 1u] = borderColor;
3879 pixels[i * 4u + 2u] = borderColor;
3880 pixels[i * 4u + 3u] = borderColor;
3884 static_assert(
sizeof(uint8x16_t) ==
sizeof(pixels),
"Invalid data type!");
3886 const uint8x16_t m128_pixels = vld1q_u8((
const uint8_t*)pixels);
3892 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
3893 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
3898 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
3899 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
3900 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
3901 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
3916 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
3918 const uint32x4_t m128_muliplicationA = vmulq_u32(vandq_u32(vreinterpretq_u32_u8(m128_pixels), m128_maskFirstByte), m128_factorsTopLeft);
3919 const uint32x4_t m128_muliplicationB = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 8), m128_maskFirstByte), m128_factorsTopRight);
3920 const uint32x4_t m128_muliplicationC = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 16), m128_maskFirstByte), m128_factorsBottomLeft);
3921 const uint32x4_t m128_muliplicationD = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 24), m128_maskFirstByte), m128_factorsBottomRight);
3923 const uint32x4_t m128_multiplication = vaddq_u32(vaddq_u32(m128_muliplicationA, m128_muliplicationB), vaddq_u32(m128_muliplicationC, m128_muliplicationD));
3927 const uint8x16_t m128_interpolation = vreinterpretq_u8_u32(vshrq_n_u32(vaddq_u32(m128_multiplication, vdupq_n_u32(8192u)), 14));
3937#if defined(__aarch64__)
3939 const uint8x8_t m64_mask0 = {0, 4, 1, 1, 1, 1, 1, 1};
3940 const uint8x8_t m64_mask1 = {1, 1, 0, 4, 1, 1, 1, 1};
3942 const uint8x8_t m64_interpolation01 = vtbl1_u8(vget_low_u8(m128_interpolation), m64_mask0);
3943 const uint8x8_t m64_interpolation23 = vtbl1_u8(vget_high_u8(m128_interpolation), m64_mask1);
3945 const uint8x8_t m64_interpolation0123 = vorr_u8(m64_interpolation01, m64_interpolation23);
3947 const uint32_t result = vget_lane_u32(vreinterpret_u32_u8(m64_interpolation0123), 0);
3948 memcpy(targetPositionPixels, &result,
sizeof(uint32_t));
3952 *((uint8_t*)targetPositionPixels + 0) = vgetq_lane_u8(m128_interpolation, 0);
3953 *((uint8_t*)targetPositionPixels + 1) = vgetq_lane_u8(m128_interpolation, 4);
3954 *((uint8_t*)targetPositionPixels + 2) = vgetq_lane_u8(m128_interpolation, 8);
3955 *((uint8_t*)targetPositionPixels + 3) = vgetq_lane_u8(m128_interpolation, 12);
3962 const uint8x16_t factorsLeft_factorsTop_128_u_8x16 = vsubq_u8(vdupq_n_u8(128u), factorsRight_factorsBottom_128_u_8x16);
3964 const uint8x8_t factorsRight_u_8x8 = vget_low_u8(factorsRight_factorsBottom_128_u_8x16);
3965 const uint16x8_t factorsBottom_u_16x8 = vmovl_u8(vget_high_u8(factorsRight_factorsBottom_128_u_8x16));
3967 const uint8x8_t factorsLeft_u_8x8 = vget_low_u8(factorsLeft_factorsTop_128_u_8x16);
3968 const uint16x8_t factorsTop_u_16x8 = vmovl_u8(vget_high_u8(factorsLeft_factorsTop_128_u_8x16));
3970 const uint16x8_t intermediateTop_u_16x8 = vmlal_u8(vmull_u8(topLeft_u_8x8, factorsLeft_u_8x8), topRight_u_8x8, factorsRight_u_8x8);
3971 const uint16x8_t intermediateBottom_u_16x8 = vmlal_u8(vmull_u8(bottomLeft_u_8x8, factorsLeft_u_8x8), bottomRight_u_8x8, factorsRight_u_8x8);
3973 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));
3974 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));
3976 const uint16x8_t result_16x8 = vcombine_u16(vrshrn_n_u32(resultA_32x4, 14), vrshrn_n_u32(resultB_32x4, 14));
3978 const uint8x8_t result_8x8 = vmovn_u16(result_16x8);
3980 vst1_u8(targetPositionPixels, result_8x8);
3984OCEAN_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)
3986 ocean_assert(source !=
nullptr);
3987 ocean_assert(targetPositionPixels !=
nullptr);
3993 PixelType topPixels[8];
3994 PixelType bottomPixels[8];
4003 for (
unsigned int i = 0u; i < 4u; ++i)
4007 *(topPixels + i * 2u + 0u) = *((
const PixelType*)(source + offsetsTopLeftElements[i]));
4008 *(topPixels + i * 2u + 1u) = *((
const PixelType*)(source + offsetsTopRightElements[i]));
4009 *(bottomPixels + i * 2u + 0u) = *((
const PixelType*)(source + offsetsBottomLeftElements[i]));
4010 *(bottomPixels + i * 2u + 1u) = *((
const PixelType*)(source + offsetsBottomRightElements[i]));
4014 *(topPixels + i * 2u + 0u) = borderColor;
4015 *(topPixels + i * 2u + 1u) = borderColor;
4016 *(bottomPixels + i * 2u + 0u) = borderColor;
4017 *(bottomPixels + i * 2u + 1u) = borderColor;
4021 static_assert(
sizeof(uint32x4_t) ==
sizeof(topPixels),
"Invalid data type!");
4023 const uint32x4_t m128_topPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topPixels));
4024 const uint32x4_t m128_bottomPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomPixels));
4030 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4031 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4036 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4037 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4038 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4039 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4042 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4044 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topPixels, m128_maskFirstByte), m128_factorsTopLeft);
4045 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4047 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4048 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 24), m128_maskFirstByte), m128_factorsTopRight));
4050 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4051 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4053 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4054 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 24), m128_maskFirstByte), m128_factorsBottomRight));
4059 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4060 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4066 const uint32x4_t m128_interpolation = vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8));
4070 const uint8x8_t m64_mask0 = {0, 1, 4, 5, 2, 2, 2, 2};
4071 const uint8x8_t m64_mask1 = {2, 2, 2, 2, 0, 1, 4, 5};
4073 const uint8x8_t m64_interpolation_low = vtbl1_u8(vget_low_u8(vreinterpretq_u8_u32(m128_interpolation)), m64_mask0);
4074 const uint8x8_t m64_interpolation_high = vtbl1_u8(vget_high_u8(vreinterpretq_u8_u32(m128_interpolation)), m64_mask1);
4076 const uint8x8_t m64_interpolation = vorr_u8(m64_interpolation_low, m64_interpolation_high);
4083 vst1_u8((uint8_t*)targetPositionPixels, m64_interpolation);
4087OCEAN_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)
4089 ocean_assert(source !=
nullptr);
4090 ocean_assert(targetPositionPixels !=
nullptr);
4094 uint32_t topLeftPixels[4];
4095 uint32_t topRightPixels[4];
4096 uint32_t bottomLeftPixels[4];
4097 uint32_t bottomRightPixels[4];
4105 for (
unsigned int i = 0u; i < 4u; ++i)
4109 memcpy(topLeftPixels + i, source + offsetsTopLeftElements[i],
sizeof(uint8_t) * 3);
4110 memcpy(topRightPixels + i, source + offsetsTopRightElements[i],
sizeof(uint8_t) * 3);
4111 memcpy(bottomLeftPixels + i, source + offsetsBottomLeftElements[i],
sizeof(uint8_t) * 3);
4112 memcpy(bottomRightPixels + i, source + offsetsBottomRightElements[i],
sizeof(uint8_t) * 3);
4116 memcpy(topLeftPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4117 memcpy(topRightPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4118 memcpy(bottomLeftPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4119 memcpy(bottomRightPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4123 static_assert(
sizeof(uint32x4_t) ==
sizeof(topLeftPixels),
"Invalid data type!");
4125 const uint32x4_t m128_topLeftPixels = vld1q_u32(topLeftPixels);
4126 const uint32x4_t m128_topRightPixels = vld1q_u32(topRightPixels);
4127 const uint32x4_t m128_bottomLeftPixels = vld1q_u32(bottomLeftPixels);
4128 const uint32x4_t m128_bottomRightPixels = vld1q_u32(bottomRightPixels);
4134 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4135 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4140 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4141 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4142 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4143 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4146 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4148 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topLeftPixels, m128_maskFirstByte), m128_factorsTopLeft);
4149 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4150 uint32x4_t m128_muliplicationChannel2 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 16), m128_maskFirstByte), m128_factorsTopLeft);
4152 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_topRightPixels, m128_maskFirstByte), m128_factorsTopRight));
4153 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 8), m128_maskFirstByte), m128_factorsTopRight));
4154 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4156 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomLeftPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4157 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4158 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 16), m128_maskFirstByte), m128_factorsBottomLeft));
4160 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomRightPixels, m128_maskFirstByte), m128_factorsBottomRight));
4161 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 8), m128_maskFirstByte), m128_factorsBottomRight));
4162 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4167 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4168 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4169 const uint32x4_t m128_interpolation2 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel2, vdupq_n_u32(8192u)), 14);
4173 const uint32x4_t m128_interpolation = vorrq_u32(vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8)), vshlq_n_u32(m128_interpolation2, 16));
4179 uint32_t intermediateBuffer[4];
4180 vst1q_u32(intermediateBuffer, m128_interpolation);
4182 for (
unsigned int i = 0u; i < 4u; ++i)
4184 memcpy(targetPositionPixels + i, intermediateBuffer + i,
sizeof(uint8_t) * 3);
4189OCEAN_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)
4191 ocean_assert(source !=
nullptr);
4192 ocean_assert(targetPositionPixels !=
nullptr);
4198 PixelType topLeftPixels[4];
4199 PixelType topRightPixels[4];
4200 PixelType bottomLeftPixels[4];
4201 PixelType bottomRightPixels[4];
4209 for (
unsigned int i = 0u; i < 4u; ++i)
4213 *(topLeftPixels + i) = *((
const PixelType*)(source + offsetsTopLeftElements[i]));
4214 *(topRightPixels + i) = *((
const PixelType*)(source + offsetsTopRightElements[i]));
4215 *(bottomLeftPixels + i) = *((
const PixelType*)(source + offsetsBottomLeftElements[i]));
4216 *(bottomRightPixels + i) = *((
const PixelType*)(source + offsetsBottomRightElements[i]));
4220 *(topLeftPixels + i) = borderColor;
4221 *(topRightPixels + i) = borderColor;
4222 *(bottomLeftPixels + i) = borderColor;
4223 *(bottomRightPixels + i) = borderColor;
4227 static_assert(
sizeof(uint32x4_t) ==
sizeof(topLeftPixels),
"Invalid data type!");
4229 const uint32x4_t m128_topLeftPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topLeftPixels));
4230 const uint32x4_t m128_topRightPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topRightPixels));
4231 const uint32x4_t m128_bottomLeftPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomLeftPixels));
4232 const uint32x4_t m128_bottomRightPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomRightPixels));
4238 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4239 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4244 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4245 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4246 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4247 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4250 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4252 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topLeftPixels, m128_maskFirstByte), m128_factorsTopLeft);
4253 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4254 uint32x4_t m128_muliplicationChannel2 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 16), m128_maskFirstByte), m128_factorsTopLeft);
4255 uint32x4_t m128_muliplicationChannel3 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 24), m128_maskFirstByte), m128_factorsTopLeft);
4257 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_topRightPixels, m128_maskFirstByte), m128_factorsTopRight));
4258 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 8), m128_maskFirstByte), m128_factorsTopRight));
4259 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4260 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 24), m128_maskFirstByte), m128_factorsTopRight));
4262 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomLeftPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4263 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4264 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 16), m128_maskFirstByte), m128_factorsBottomLeft));
4265 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 24), m128_maskFirstByte), m128_factorsBottomLeft));
4267 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomRightPixels, m128_maskFirstByte), m128_factorsBottomRight));
4268 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 8), m128_maskFirstByte), m128_factorsBottomRight));
4269 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4270 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 24), m128_maskFirstByte), m128_factorsBottomRight));
4275 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4276 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4277 const uint32x4_t m128_interpolation2 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel2, vdupq_n_u32(8192u)), 14);
4278 const uint32x4_t m128_interpolation3 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel3, vdupq_n_u32(8192u)), 14);
4282 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)));
4284 vst1q_u8((uint8_t*)targetPositionPixels, vreinterpretq_u8_u32(m128_interpolation));
4287template <
unsigned int tChannels>
4288OCEAN_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)
4290 ocean_assert(source !=
nullptr);
4291 ocean_assert(targetPositionPixels !=
nullptr);
4295 unsigned int factorsTopLeft[4];
4296 unsigned int factorsTopRight[4];
4297 unsigned int factorsBottomLeft[4];
4298 unsigned int factorsBottomRight[4];
4304 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4305 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4310 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4311 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4312 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4313 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4317 vst1q_u32(factorsTopLeft, m128_factorsTopLeft);
4318 vst1q_u32(factorsTopRight, m128_factorsTopRight);
4319 vst1q_u32(factorsBottomLeft, m128_factorsBottomLeft);
4320 vst1q_u32(factorsBottomRight, m128_factorsBottomRight);
4322 for (
unsigned int i = 0u; i < 4u; ++i)
4326 const uint8_t* topLeft = source + offsetsTopLeftElements[i];
4327 const uint8_t* topRight = source + offsetsTopRightElements[i];
4329 const uint8_t* bottomLeft = source + offsetsBottomLeftElements[i];
4330 const uint8_t* bottomRight = source + offsetsBottomRightElements[i];
4332 const unsigned int& factorTopLeft = factorsTopLeft[i];
4333 const unsigned int& factorTopRight = factorsTopRight[i];
4334 const unsigned int& factorBottomLeft = factorsBottomLeft[i];
4335 const unsigned int& factorBottomRight = factorsBottomRight[i];
4337 for (
unsigned int n = 0u; n < tChannels; ++n)
4339 ((uint8_t*)targetPositionPixels)[n] = (topLeft[n] * factorTopLeft + topRight[n] * factorTopRight + bottomLeft[n] * factorBottomLeft + bottomRight[n] * factorBottomRight + 8192u) >> 14u;
4344 *targetPositionPixels = borderColor;
4347 targetPositionPixels++;
4353template <
unsigned int tChannels>
4354inline 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)
4356 static_assert(tChannels >= 1u,
"Invalid channel number!");
4358 ocean_assert(input && output);
4359 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4360 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4362 ocean_assert(outputQuadrantCenterX >= 0 && outputQuadrantCenterX <
Scalar(outputWidth));
4363 ocean_assert(outputQuadrantCenterY >= 0 && outputQuadrantCenterY <
Scalar(outputHeight));
4364 ocean_assert(homographies);
4366 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
4368 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4369 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4371 constexpr uint8_t zeroColor[tChannels] = {uint8_t(0)};
4372 const uint8_t*
const bColor = borderColor ? borderColor : zeroColor;
4374 uint8_t* outputData = output + firstOutputRow * outputStrideElements;
4388 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4390 for (
unsigned int x = 0; x < outputWidth; ++x)
4394 const Scalar _tx = minmax<Scalar>(0, (outputPosition.
x() - left) * invWidth, 1);
4395 const Scalar _ty = minmax<Scalar>(0, (outputPosition.
y() - top) * invHeight, 1);
4399 const Scalar tx = 1 - _tx;
4400 const Scalar ty = 1 - _ty;
4402 const Vector2 inputPositionTopLeft(homographies[0] * outputPosition);
4403 const Vector2 inputPositionTopRight(homographies[1] * outputPosition);
4404 const Vector2 inputPositionBottomLeft(homographies[2] * outputPosition);
4405 const Vector2 inputPositionBottomRight(homographies[3] * outputPosition);
4407 const Scalar tTopLeft = tx * ty;
4408 const Scalar tTopRight = _tx * ty;
4409 const Scalar tBottomLeft = tx * _ty;
4410 const Scalar tBottomRight = _tx * _ty;
4412 const Vector2 inputPosition = inputPositionTopLeft * tTopLeft + inputPositionTopRight * tTopRight
4413 + inputPositionBottomLeft * tBottomLeft + inputPositionBottomRight * tBottomRight;
4415 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4417 for (
unsigned int c = 0u; c < tChannels; ++c)
4419 outputData[c] = bColor[c];
4424 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, outputData);
4427 outputData += tChannels;
4430 outputData += outputPaddingElements;
4434template <
unsigned int tChannels>
4435void 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)
4437 static_assert(tChannels >= 1u,
"Invalid channel number!");
4439 ocean_assert(input !=
nullptr && output !=
nullptr);
4440 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4441 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4442 ocean_assert(input_H_output !=
nullptr);
4444 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
4446 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
4447 const unsigned int outputMaskStrideElements = outputWidth + outputMaskPaddingElements;
4449 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4450 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4454 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4456 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4457 uint8_t* outputMaskData = outputMask + y * outputMaskStrideElements;
4481 const Scalar X2 = (*input_H_output)(2, 0);
4482 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
4484 for (
unsigned int x = 0; x < outputWidth; ++x)
4490 ocean_assert(inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
4493 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4495 *outputMaskData = 0xFF - maskValue;
4499 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
4500 *outputMaskData = maskValue;
4509template <
unsigned int tChannels>
4510inline 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)
4512 static_assert(tChannels >= 1u,
"Invalid channel number!");
4514 ocean_assert(input && output);
4515 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4516 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4518 ocean_assert(outputQuadrantCenterX >= 0 && outputQuadrantCenterX <
Scalar(outputWidth));
4519 ocean_assert(outputQuadrantCenterY >= 0 && outputQuadrantCenterY <
Scalar(outputHeight));
4520 ocean_assert(homographies);
4522 const unsigned int outputStrideElements = tChannels * outputWidth + outputPaddingElements;
4523 const unsigned int outputMaskStrideElements = outputWidth + outputMaskPaddingElements;
4525 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4526 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4528 uint8_t* outputData = output + firstOutputRow * outputStrideElements;
4529 outputMask += firstOutputRow * outputMaskStrideElements;
4543 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4545 for (
unsigned int x = 0u; x < outputWidth; ++x)
4549 const Scalar _tx = minmax<Scalar>(0, (outputPosition.
x() - left) * invWidth, 1);
4550 const Scalar _ty = minmax<Scalar>(0, (outputPosition.
y() - top) * invHeight, 1);
4554 const Scalar tx = 1 - _tx;
4555 const Scalar ty = 1 - _ty;
4557 const Vector2 inputPositionTopLeft(homographies[0] * outputPosition);
4558 const Vector2 inputPositionTopRight(homographies[1] * outputPosition);
4559 const Vector2 inputPositionBottomLeft(homographies[2] * outputPosition);
4560 const Vector2 inputPositionBottomRight(homographies[3] * outputPosition);
4562 const Scalar tTopLeft = tx * ty;
4563 const Scalar tTopRight = _tx * ty;
4564 const Scalar tBottomLeft = tx * _ty;
4565 const Scalar tBottomRight = _tx * _ty;
4567 const Vector2 inputPosition = inputPositionTopLeft * tTopLeft + inputPositionTopRight * tTopRight
4568 + inputPositionBottomLeft * tBottomLeft + inputPositionBottomRight * tBottomRight;
4570 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4572 *outputMask = 0xFFu - maskValue;
4576 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, outputData);
4577 *outputMask = maskValue;
4580 outputData += tChannels;
4584 outputData += outputPaddingElements;
4585 outputMask += outputMaskPaddingElements;
4589template <
unsigned int tChannels>
4590void 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)
4592 static_assert(tChannels >= 1u,
"Invalid channel number!");
4594 ocean_assert(inputCamera && outputCamera && normalizedHomography);
4595 ocean_assert(input && output);
4597 ocean_assert(firstRow + numberRows <= outputCamera->height());
4599 const unsigned int outputStrideElements = tChannels * outputCamera->
width() + outputPaddingElements;
4608 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
4609 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4611 uint8_t* outputData = output + firstRow * outputStrideElements;
4613 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4615 for (
unsigned int x = 0; x < outputCamera->
width(); ++x)
4619 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4621 *((PixelType*)outputData) = *bColor;
4625 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputCamera->
width(), inputCamera->
height(), inputPaddingElements, inputPosition, outputData);
4628 outputData += tChannels;
4631 outputData += outputPaddingElements;
4635template <
unsigned int tChannels>
4636void 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)
4638 static_assert(tChannels >= 1u,
"Invalid channel number!");
4640 ocean_assert(inputCamera !=
nullptr && outputCamera !=
nullptr && normalizedHomography !=
nullptr);
4641 ocean_assert(input !=
nullptr && output !=
nullptr);
4643 ocean_assert(firstRow + numberRows <= outputCamera->height());
4645 const unsigned int outputStrideElements = outputCamera->
width() * tChannels + outputPaddingElements;
4646 const unsigned int outputMaskStrideElements = outputCamera->
width() + outputMaskPaddingElements;
4653 uint8_t* outputData = output + firstRow * outputStrideElements;
4654 outputMask += firstRow * outputMaskStrideElements;
4656 constexpr bool useDistortionParameters =
true;
4658 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4660 for (
unsigned int x = 0; x < outputCamera->
width(); ++x)
4664 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4666 *outputMask = 0xFF - maskValue;
4670 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputCamera->
width(), inputCamera->
height(), inputPaddingElements, inputPosition, outputData);
4671 *outputMask = maskValue;
4674 outputData += tChannels;
4678 outputData += outputPaddingElements;
4679 outputMask += outputMaskPaddingElements;
4683template <
unsigned int tChannels>
4684void 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)
4686 static_assert(tChannels >= 1u,
"Invalid channel number!");
4688 ocean_assert(input_LT_output !=
nullptr);
4689 ocean_assert(input !=
nullptr && output !=
nullptr);
4691 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4692 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4696 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
4697 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4699 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
4701 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
4703 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4708 Memory rowLookupMemory = Memory::create<Vector2>(columns);
4711 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4715 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4717 for (
unsigned int x = 0u; x < columns; ++x)
4719 const Vector2& lookupValue = rowLookupData[x];
4723 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
y() >=
Scalar(0) && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
4725 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
4729 *outputData = *bColor;
4737template <
typename T,
unsigned int tChannels>
4738void 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)
4740 static_assert(tChannels >= 1u,
"Invalid channel number!");
4742 ocean_assert((!std::is_same<uint8_t, T>::value));
4744 ocean_assert(input_LT_output !=
nullptr);
4745 ocean_assert(input !=
nullptr && output !=
nullptr);
4747 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4748 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4752 const T zeroColor[tChannels] = {T(0)};
4753 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4755 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
4757 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
4759 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4764 Memory rowLookupMemory = Memory::create<Vector2>(columns);
4767 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4771 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4773 for (
unsigned int x = 0u; x < columns; ++x)
4775 const Vector2& lookupValue = rowLookupData[x];
4779 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
y() >=
Scalar(0) && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
4781 interpolatePixel<T, T, tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (T*)(outputData));
4785 *outputData = *bColor;
4793#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
4796inline 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)
4798 ocean_assert(input_LT_output !=
nullptr);
4799 ocean_assert(input !=
nullptr && output !=
nullptr);
4801 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4802 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4804 typedef uint8_t PixelType;
4806 const uint8x16_t constantBorderColor_u_8x16 = vdupq_n_u8(borderColor ? *borderColor : 0u);
4808 const unsigned int outputWidth = (
unsigned int)(input_LT_output->
sizeX());
4809 ocean_assert(outputWidth >= 8u);
4811 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4813 const unsigned int inputStrideElements = inputWidth + inputPaddingElements;
4814 const unsigned int outputStrideElements = outputWidth + outputPaddingElements;
4816 Memory rowLookupMemory = Memory::create<VectorF2>(outputWidth);
4819 const float32x4_t constantZero_f_32x4 = vdupq_n_f32(0.0f);
4820 const float32x4_t constantEight_f_32x4 = vdupq_n_f32(8.0f);
4823 const float f_01234567[8] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
4824 const float32x4_t conststant0123_f_32x4 = vld1q_f32(f_01234567 + 0);
4825 const float32x4_t conststant4567_f_32x4 = vld1q_f32(f_01234567 + 4);
4827 const float32x4_t constant128_f_32x4 = vdupq_n_f32(128.0f);
4829 const uint32x4_t constantOne_u_32x4 = vdupq_n_u32(1u);
4831 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(1u);
4833 const float32x4_t constantInputWidth1_f_32x4 = vdupq_n_f32(
float(inputWidth - 1u));
4834 const float32x4_t constantInputHeight1_f_32x4 = vdupq_n_f32(
float(inputHeight - 1u));
4836 const uint32x4_t constantInputStrideElements_u_32x4 = vdupq_n_u32(inputStrideElements);
4837 const uint32x4_t constantInputHeight1_u_32x4 = vdupq_n_u32(inputHeight - 1u);
4839 unsigned int validPixels[8];
4841 unsigned int topLeftOffsetsElements[8];
4842 unsigned int bottomLeftOffsetsElements[8];
4846 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4848 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
4852 float32x4_t additionalInputOffsetX0123_f_32x4 = conststant0123_f_32x4;
4853 float32x4_t additionalInputOffsetX4567_f_32x4 = conststant4567_f_32x4;
4855 const float32x4_t additionalInputOffsetY_f_32x4 = vdupq_n_f32(
float(y));
4857 for (
unsigned int x = 0u; x < outputWidth; x += 8u)
4859 if (x + 8u > outputWidth)
4864 ocean_assert(x >= 8u && outputWidth > 8u);
4865 const unsigned int newX = outputWidth - 8u;
4867 ocean_assert(x > newX);
4868 const unsigned int xOffset = x - newX;
4870 outputPixelData -= xOffset;
4874 additionalInputOffsetX0123_f_32x4 = vsubq_f32(additionalInputOffsetX0123_f_32x4, vdupq_n_f32(
float(xOffset)));
4875 additionalInputOffsetX4567_f_32x4 = vsubq_f32(additionalInputOffsetX4567_f_32x4, vdupq_n_f32(
float(xOffset)));
4881 ocean_assert(!(x + 8u < outputWidth));
4884 const float32x4x2_t inputPositions0123_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x + 0u));
4885 const float32x4x2_t inputPositions4567_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x + 4u));
4887 float32x4_t inputPositionsX0123_f_32x4 = inputPositions0123_f_32x4x2.val[0];
4888 float32x4_t inputPositionsY0123_f_32x4 = inputPositions0123_f_32x4x2.val[1];
4890 float32x4_t inputPositionsX4567_f_32x4 = inputPositions4567_f_32x4x2.val[0];
4891 float32x4_t inputPositionsY4567_f_32x4 = inputPositions4567_f_32x4x2.val[1];
4895 inputPositionsX0123_f_32x4 = vaddq_f32(inputPositionsX0123_f_32x4, additionalInputOffsetX0123_f_32x4);
4896 inputPositionsY0123_f_32x4 = vaddq_f32(inputPositionsY0123_f_32x4, additionalInputOffsetY_f_32x4);
4898 inputPositionsX4567_f_32x4 = vaddq_f32(inputPositionsX4567_f_32x4, additionalInputOffsetX4567_f_32x4);
4899 inputPositionsY4567_f_32x4 = vaddq_f32(inputPositionsY4567_f_32x4, additionalInputOffsetY_f_32x4);
4901 additionalInputOffsetX0123_f_32x4 = vaddq_f32(additionalInputOffsetX0123_f_32x4, constantEight_f_32x4);
4902 additionalInputOffsetX4567_f_32x4 = vaddq_f32(additionalInputOffsetX4567_f_32x4, constantEight_f_32x4);
4906 const uint32x4_t validPixelsX0123_u_32x4 = vandq_u32(vcltq_f32(inputPositionsX0123_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX0123_f_32x4, constantZero_f_32x4));
4907 const uint32x4_t validPixelsX4567_u_32x4 = vandq_u32(vcltq_f32(inputPositionsX4567_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX4567_f_32x4, constantZero_f_32x4));
4909 const uint32x4_t validPixelsY0123_u_32x4 = vandq_u32(vcltq_f32(inputPositionsY0123_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY0123_f_32x4, constantZero_f_32x4));
4910 const uint32x4_t validPixelsY4567_u_32x4 = vandq_u32(vcltq_f32(inputPositionsY4567_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY4567_f_32x4, constantZero_f_32x4));
4912 const uint32x4_t validPixels0123_u_32x4 = vandq_u32(validPixelsX0123_u_32x4, validPixelsY0123_u_32x4);
4913 const uint32x4_t validPixels4567_u_32x4 = vandq_u32(validPixelsX4567_u_32x4, validPixelsY4567_u_32x4);
4915 vst1q_u32(validPixels + 0, validPixels0123_u_32x4);
4916 vst1q_u32(validPixels + 4, validPixels4567_u_32x4);
4919 const uint32x4_t inputPositionsLeft0123_u_32x4 = vcvtq_u32_f32(inputPositionsX0123_f_32x4);
4920 const uint32x4_t inputPositionsLeft4567_u_32x4 = vcvtq_u32_f32(inputPositionsX4567_f_32x4);
4922 const uint32x4_t inputPositionsTop0123_u_32x4 = vcvtq_u32_f32(inputPositionsY0123_f_32x4);
4923 const uint32x4_t inputPositionsTop4567_u_32x4 = vcvtq_u32_f32(inputPositionsY4567_f_32x4);
4925 const uint32x4_t inputPositionsBottom0123_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop0123_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
4926 const uint32x4_t inputPositionsBottom4567_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop4567_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
4929 const uint32x4_t topLeftOffsetsElements0123_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft0123_u_32x4, constantChannels_u_32x4), inputPositionsTop0123_u_32x4, constantInputStrideElements_u_32x4);
4930 vst1q_u32(topLeftOffsetsElements + 0, topLeftOffsetsElements0123_u_32x4);
4931 const uint32x4_t topLeftOffsetsElements4567_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft4567_u_32x4, constantChannels_u_32x4), inputPositionsTop4567_u_32x4, constantInputStrideElements_u_32x4);
4932 vst1q_u32(topLeftOffsetsElements + 4, topLeftOffsetsElements4567_u_32x4);
4934 const uint32x4_t bottomLeftOffsetsElements0123_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft0123_u_32x4, constantChannels_u_32x4), inputPositionsBottom0123_u_32x4, constantInputStrideElements_u_32x4);
4935 vst1q_u32(bottomLeftOffsetsElements + 0, bottomLeftOffsetsElements0123_u_32x4);
4936 const uint32x4_t bottomLeftOffsetsElements4567_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft4567_u_32x4, constantChannels_u_32x4), inputPositionsBottom4567_u_32x4, constantInputStrideElements_u_32x4);
4937 vst1q_u32(bottomLeftOffsetsElements + 4, bottomLeftOffsetsElements4567_u_32x4);
4941 float32x4_t tx0123_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX0123_f_32x4, vcvtq_f32_u32(inputPositionsLeft0123_u_32x4)), constant128_f_32x4);
4942 float32x4_t tx4567_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX4567_f_32x4, vcvtq_f32_u32(inputPositionsLeft4567_u_32x4)), constant128_f_32x4);
4944 float32x4_t ty0123_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY0123_f_32x4, vcvtq_f32_u32(inputPositionsTop0123_u_32x4)), constant128_f_32x4);
4945 float32x4_t ty4567_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY4567_f_32x4, vcvtq_f32_u32(inputPositionsTop4567_u_32x4)), constant128_f_32x4);
4947 const uint32x4_t tx0123_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx0123_f_32x4, vdupq_n_f32(0.5)));
4948 const uint32x4_t tx4567_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx4567_f_32x4, vdupq_n_f32(0.5)));
4950 const uint32x4_t ty0123_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty0123_f_32x4, vdupq_n_f32(0.5)));
4951 const uint32x4_t ty4567_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty4567_f_32x4, vdupq_n_f32(0.5)));
4953 const uint16x8_t tx01234567_128_u_16x8 = vcombine_u16(vmovn_u32(tx0123_128_u_32x4), vmovn_u32(tx4567_128_u_32x4));
4954 const uint16x8_t ty01234567_128_u_16x8 = vcombine_u16(vmovn_u32(ty0123_128_u_32x4), vmovn_u32(ty4567_128_u_32x4));
4956 const uint8x16_t tx_ty_128_u_8x16 = vcombine_u8(vmovn_u16(tx01234567_128_u_16x8), vmovn_u16(ty01234567_128_u_16x8));
4959 vst1q_u8(pixels + 0, constantBorderColor_u_8x16);
4960 vst1q_u8(pixels + 16, constantBorderColor_u_8x16);
4962 struct LeftRightPixel
4968 static_assert(
sizeof(LeftRightPixel) == 2,
"Invalid data type!");
4972 for (
unsigned int i = 0u; i < 8u; ++i)
4976 ocean_assert((topLeftOffsetsElements[i] % inputStrideElements) < inputWidth - 1u);
4977 ocean_assert((bottomLeftOffsetsElements[i] % inputStrideElements) < inputWidth - 1u);
4979 ((LeftRightPixel*)pixels)[0u + i] = *(LeftRightPixel*)(input + topLeftOffsetsElements[i]);
4980 ((LeftRightPixel*)pixels)[8u + i] = *(LeftRightPixel*)(input + bottomLeftOffsetsElements[i]);
4984 const uint8x8x2_t topLeft_topRight_u_8x8x2 = vld2_u8(pixels);
4985 const uint8x8x2_t bottomLeft_bottomRight_u_8x8x2 = vld2_u8(pixels + 16);
4987 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);
4989 outputPixelData += 8;
4994template <
unsigned int tChannels>
4995void 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)
4997 ocean_assert(input_LT_output !=
nullptr);
4998 ocean_assert(input !=
nullptr && output !=
nullptr);
5000 ocean_assert(inputWidth != 0u && inputHeight != 0u);
5001 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
5005 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
5006 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
5008 const unsigned int outputWidth = (
unsigned int)(input_LT_output->
sizeX());
5009 ocean_assert(outputWidth >= 4u);
5011 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5013 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
5014 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
5016 Memory rowLookupMemory = Memory::create<VectorF2>(outputWidth);
5019 const float32x4_t constantZero_f_32x4 = vdupq_n_f32(0.0f);
5020 const float32x4_t constantFour_f_32x4 = vdupq_n_f32(4.0f);
5023 const float f_0123[4] = {0.0f, 1.0f, 2.0f, 3.0f};
5024 float32x4_t conststant0123_f_32x4 = vld1q_f32(f_0123);
5026 const uint32x4_t constantOne_u_32x4 = vdupq_n_u32(1u);
5028 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
5030 const float32x4_t constantInputWidth1_f_32x4 = vdupq_n_f32(
float(inputWidth - 1u));
5031 const float32x4_t constantInputHeight1_f_32x4 = vdupq_n_f32(
float(inputHeight - 1u));
5033 const uint32x4_t constantInputStrideElements_u_32x4 = vdupq_n_u32(inputStrideElements);
5034 const uint32x4_t constantInputWidth1_u_32x4 = vdupq_n_u32(inputWidth - 1u);
5035 const uint32x4_t constantInputHeight1_u_32x4 = vdupq_n_u32(inputHeight - 1u);
5037 unsigned int validPixels[4];
5039 unsigned int topLeftOffsetsElements[4];
5040 unsigned int topRightOffsetsElements[4];
5041 unsigned int bottomLeftOffsetsElements[4];
5042 unsigned int bottomRightOffsetsElements[4];
5044 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5046 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
5050 float32x4_t additionalInputOffsetX_f_32x4 = conststant0123_f_32x4;
5051 const float32x4_t additionalInputOffsetY_f_32x4 = vdupq_n_f32(
float(y));
5053 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
5055 if (x + 4u > outputWidth)
5060 ocean_assert(x >= 4u && outputWidth > 4u);
5061 const unsigned int newX = outputWidth - 4u;
5063 ocean_assert(x > newX);
5064 const unsigned int xOffset = x - newX;
5066 outputPixelData -= xOffset;
5070 additionalInputOffsetX_f_32x4 = vsubq_f32(additionalInputOffsetX_f_32x4, vdupq_n_f32(
float(xOffset)));
5076 ocean_assert(!(x + 4u < outputWidth));
5079 const float32x4x2_t inputPositions_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x));
5081 float32x4_t inputPositionsX_f_32x4 = inputPositions_f_32x4x2.val[0];
5082 float32x4_t inputPositionsY_f_32x4 = inputPositions_f_32x4x2.val[1];
5086 inputPositionsX_f_32x4 = vaddq_f32(inputPositionsX_f_32x4, additionalInputOffsetX_f_32x4);
5087 inputPositionsY_f_32x4 = vaddq_f32(inputPositionsY_f_32x4, additionalInputOffsetY_f_32x4);
5089 additionalInputOffsetX_f_32x4 = vaddq_f32(additionalInputOffsetX_f_32x4, constantFour_f_32x4);
5093 const uint32x4_t validPixelsX_u_32x4 = vandq_u32(vcleq_f32(inputPositionsX_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX_f_32x4, constantZero_f_32x4));
5094 const uint32x4_t validPixelsY_u_32x4 = vandq_u32(vcleq_f32(inputPositionsY_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY_f_32x4, constantZero_f_32x4));
5096 const uint32x4_t validPixels_u_32x4 = vandq_u32(validPixelsX_u_32x4, validPixelsY_u_32x4);
5098 vst1q_u32(validPixels, validPixels_u_32x4);
5100 const uint32x4_t inputPositionsLeft_u_32x4 = vcvtq_u32_f32(inputPositionsX_f_32x4);
5101 const uint32x4_t inputPositionsTop_u_32x4 = vcvtq_u32_f32(inputPositionsY_f_32x4);
5103 const uint32x4_t inputPositionsRight_u_32x4 = vminq_u32(vaddq_u32(inputPositionsLeft_u_32x4, constantOne_u_32x4), constantInputWidth1_u_32x4);
5104 const uint32x4_t inputPositionsBottom_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
5106 const uint32x4_t topLeftOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft_u_32x4, constantChannels_u_32x4), inputPositionsTop_u_32x4, constantInputStrideElements_u_32x4);
5107 const uint32x4_t topRightOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsRight_u_32x4, constantChannels_u_32x4), inputPositionsTop_u_32x4, constantInputStrideElements_u_32x4);
5108 const uint32x4_t bottomLeftOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft_u_32x4, constantChannels_u_32x4), inputPositionsBottom_u_32x4, constantInputStrideElements_u_32x4);
5109 const uint32x4_t bottomRightOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsRight_u_32x4, constantChannels_u_32x4), inputPositionsBottom_u_32x4, constantInputStrideElements_u_32x4);
5111 vst1q_u32(topLeftOffsetsElements, topLeftOffsetsElements_u_32x4);
5112 vst1q_u32(topRightOffsetsElements, topRightOffsetsElements_u_32x4);
5113 vst1q_u32(bottomLeftOffsetsElements, bottomLeftOffsetsElements_u_32x4);
5114 vst1q_u32(bottomRightOffsetsElements, bottomRightOffsetsElements_u_32x4);
5117 float32x4_t tx_f_32x4 = vsubq_f32(inputPositionsX_f_32x4, vcvtq_f32_u32(inputPositionsLeft_u_32x4));
5118 float32x4_t ty_f_32x4 = vsubq_f32(inputPositionsY_f_32x4, vcvtq_f32_u32(inputPositionsTop_u_32x4));
5121 tx_f_32x4 = vmulq_f32(tx_f_32x4, vdupq_n_f32(128.0f));
5122 ty_f_32x4 = vmulq_f32(ty_f_32x4, vdupq_n_f32(128.0f));
5124 const uint32x4_t tx_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx_f_32x4, vdupq_n_f32(0.5)));
5125 const uint32x4_t ty_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty_f_32x4, vdupq_n_f32(0.5)));
5127 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, tx_128_u_32x4, ty_128_u_32x4, outputPixelData);
5129 outputPixelData += 4;
5136template <
unsigned int tChannels>
5137void 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)
5139 ocean_assert(input_LT_output !=
nullptr);
5140 ocean_assert(input !=
nullptr && output !=
nullptr);
5142 ocean_assert(inputWidth != 0u && inputHeight != 0u);
5143 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
5147 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
5149 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
5150 const unsigned int outputMaskStrideElements = columns + outputMaskPaddingElements;
5152 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5157 Memory rowLookupMemory = Memory::create<Vector2>(columns);
5160 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5164 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
5165 uint8_t* outputMaskData = outputMask + y * outputMaskStrideElements;
5167 for (
unsigned int x = 0u; x < columns; ++x)
5169 const Vector2& lookupValue = rowLookupData[x];
5173 if (inputPosition.
x() >= 0 && inputPosition.
y() >= 0 && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
5175 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
5176 *outputMaskData = maskValue;
5180 *outputMaskData = 0xFFu - maskValue;
5189template <
unsigned int tChannels>
5190void 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)
5192 ocean_assert(source !=
nullptr && target !=
nullptr);
5193 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
5194 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
5195 ocean_assert(sourceX_s_targetX > 0.0);
5196 ocean_assert(sourceY_s_targetY > 0.0);
5198 if (sourceWidth == targetWidth && sourceHeight == targetHeight)
5200 FrameConverter::subFrame<uint8_t>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, 0u, 0u, 0u, 0u, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements);
5204 if (worker && sourceWidth * tChannels >= 16u && targetWidth >= 8u)
5206#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5207 if (sourceWidth <= 65535u && sourceHeight <= 65535u && targetWidth <= 65535u && targetHeight <= 65535u)
5209 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);
5213 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);
5218 if (sourceWidth * tChannels >= 16u && targetWidth >= 8u)
5220#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5221 if (sourceWidth <= 65535u && sourceHeight <= 65535u && targetWidth <= 65535u && targetHeight <= 65535u)
5223 scale8BitPerChannelSubset7BitPrecisionNEON(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
5229 scale8BitPerChannelSubset<tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
5233template <
unsigned int tChannels>
5234void 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)
5236 ocean_assert(source !=
nullptr && target !=
nullptr);
5237 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
5238 ocean_assert_and_suppress_unused(targetWidth >= 1u && targetHeight >= 1u, targetHeight);
5239 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5241 const Scalar sourceX_T_targetX =
Scalar(sourceX_s_targetX);
5242 const Scalar sourceY_T_targetY =
Scalar(sourceY_s_targetY);
5290 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
5292 const Scalar sourceX_T_targetXOffset = sourceX_T_targetX *
Scalar(0.5) -
Scalar(0.5);
5293 const Scalar sourceY_T_targetYOffset = sourceY_T_targetY *
Scalar(0.5) -
Scalar(0.5);
5296 const Scalar sourceHeight_1 =
Scalar(sourceHeight - 1u);
5298 target += (targetWidth * tChannels + targetPaddingElements) * firstTargetRow;
5300 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5303 ocean_assert(sy >=
Scalar(0) && sy <
Scalar(sourceHeight));
5305 const unsigned int sTop = (
unsigned int)sy;
5306 ocean_assert(sy >=
Scalar(sTop));
5309 ocean_assert(ty >= 0 && ty <= 1);
5311 const unsigned int factorBottom = (
unsigned int)(ty *
Scalar(128) +
Scalar(0.5));
5312 const unsigned int factorTop = 128u - factorBottom;
5314 const uint8_t*
const sourceTop = source + sourceStrideElements * sTop;
5315 const uint8_t*
const sourceBottom = (sTop + 1u < sourceHeight) ? sourceTop + sourceStrideElements : sourceTop;
5317 for (
unsigned int x = 0; x < targetWidth; ++x)
5320 ocean_assert(sx >=
Scalar(0) && sx <
Scalar(sourceWidth));
5322 const unsigned int sLeft = (
unsigned int)sx;
5323 ocean_assert(sx >=
Scalar(sLeft));
5326 ocean_assert(tx >= 0 && tx <= 1);
5328 const unsigned int factorRight = (
unsigned int)(tx *
Scalar(128) +
Scalar(0.5));
5329 const unsigned int factorLeft = 128u - factorRight;
5331 const unsigned int sourceRightOffset = sLeft + 1u < sourceWidth ? tChannels : 0u;
5333 const uint8_t*
const sourceTopLeft = sourceTop + sLeft * tChannels;
5334 const uint8_t*
const sourceBottomLeft = sourceBottom + sLeft * tChannels;
5336 const unsigned int factorTopLeft = factorTop * factorLeft;
5337 const unsigned int factorTopRight = factorTop * factorRight;
5338 const unsigned int factorBottomLeft = factorBottom * factorLeft;
5339 const unsigned int factorBottomRight = factorBottom * factorRight;
5341 for (
unsigned int n = 0u; n < tChannels; ++n)
5343 target[n] = (uint8_t)((sourceTopLeft[n] * factorTopLeft + sourceTopLeft[sourceRightOffset + n] * factorTopRight
5344 + sourceBottomLeft[n] * factorBottomLeft + sourceBottomLeft[sourceRightOffset + n] * factorBottomRight + 8192u) >> 14u);
5347 target += tChannels;
5350 target += targetPaddingElements;
5354template <
typename T>
5357 ocean_assert(sourceRowTop !=
nullptr);
5358 ocean_assert(sourceRowBottom !=
nullptr);
5359 ocean_assert(targetRow !=
nullptr);
5360 ocean_assert(elements >= 1u);
5361 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
5365 const FloatType internalFactorBottom = FloatType(factorBottom);
5366 const FloatType internalFactorTop = FloatType(1.0f - factorBottom);
5368 for (
unsigned int n = 0u; n < elements; ++n)
5370 targetRow[n] = T(FloatType(sourceRowTop[n]) * internalFactorTop + FloatType(sourceRowBottom[n]) * internalFactorBottom);
5374template <
typename T,
unsigned int tChannels>
5377 static_assert(tChannels != 0u,
"Invalid channel number!");
5379 ocean_assert(extendedSourceRow !=
nullptr);
5380 ocean_assert(targetRow !=
nullptr);
5381 ocean_assert(targetWidth >= 1u);
5382 ocean_assert(interpolationLocations !=
nullptr);
5383 ocean_assert(interpolationFactorsRight !=
nullptr);
5384 ocean_assert(channels == tChannels);
5388 for (
unsigned int x = 0u; x < targetWidth; ++x)
5390 const FloatType internalFactorRight = FloatType(interpolationFactorsRight[x]);
5391 ocean_assert(internalFactorRight >= FloatType(0) && internalFactorRight <= FloatType(1));
5393 const FloatType internalFactorLeft = FloatType(1.0f - interpolationFactorsRight[x]);
5395 const unsigned int& leftLocation = interpolationLocations[x];
5396 const unsigned int rightLocation = leftLocation + tChannels;
5398 for (
unsigned int n = 0u; n < tChannels; ++n)
5400 targetRow[x * tChannels + n] = T(FloatType(extendedSourceRow[leftLocation + n]) * internalFactorLeft + FloatType(extendedSourceRow[rightLocation + n]) * internalFactorRight);
5405#if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5407#ifdef OCEAN_WE_KEEP_THIS_IMPLEMENTATION_AS_WE_NEED_THIS_TO_FOR_A_NEW_NEON_IMPLEMENTATION
5410inline 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)
5412 ocean_assert(source !=
nullptr && target !=
nullptr);
5413 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5414 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
5415 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
5416 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5417 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5419 ocean_assert(sourcePaddingElements == 0u);
5420 ocean_assert(targetPaddingElements == 0u);
5424 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5425 const PixelType*
const sourcePixelData = (
const PixelType*)source;
5428 unsigned int leftOffsets[8];
5441 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5442 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5444 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5445 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5448 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5451 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5454 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5457 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5459 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5460 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5462 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5464 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5466 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5467 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5468 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5470 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5472 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5474 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
5476 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
5477 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
5479 for (
unsigned int x = 0; x < targetWidth; x += 8u)
5481 if (x + 8u > targetWidth)
5486 ocean_assert(x >= 8u && targetWidth > 8u);
5487 const unsigned int newX = targetWidth - 8u;
5489 ocean_assert(x > newX);
5490 targetPixelData -= x - newX;
5495 ocean_assert(!(x + 8u < targetWidth));
5501 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
5502 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
5505 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))));
5506 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
5508 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))));
5509 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
5513 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
5514 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
5517 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
5518 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
5525 uint8x8x2_t topLeftPixels;
5526 uint8x8x2_t topRightPixels;
5528 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
5529 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
5531 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
5532 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
5534 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
5535 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
5537 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
5538 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
5540 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
5541 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
5543 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
5544 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
5546 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
5547 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
5549 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
5550 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
5555 uint8x8x2_t bottomLeftPixels;
5556 uint8x8x2_t bottomRightPixels;
5558 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
5559 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
5561 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
5562 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
5564 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
5565 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
5567 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
5568 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
5570 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
5571 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
5573 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
5574 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
5576 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
5577 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
5579 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
5580 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
5588 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5589 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5592 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
5593 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
5594 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
5599 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
5600 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
5602 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
5603 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
5605 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5606 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5611 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
5612 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
5614 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
5615 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
5617 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5618 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5623 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
5624 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
5626 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
5627 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
5632 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5633 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5636 vst2_u8((uint8_t*)targetPixelData, result);
5638 targetPixelData += 8;
5644 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
5646 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
5648 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
5650 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
5651 ocean_assert(lastSourcePixelLeft < sourceWidth);
5652 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
5654 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
5656 const unsigned int factorRight = factorRight_fixed16 >> 9u;
5657 const unsigned int factorLeft = 128u - factorRight;
5659 for (
unsigned int c = 0u; c < 2u; ++c)
5661 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
5662 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
5670#ifdef OCEAN_WE_KEEP_ALSO_THIS_SLOW_IMPLEMENTATION_SHOWING_A_SLIGHTLY_DIFFERENT_APPROACH
5673inline 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)
5675 ocean_assert(source !=
nullptr && target !=
nullptr);
5676 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5677 ocean_assert(sourceHeight >= 0u && sourceHeight <= 65535u);
5678 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u)
5679 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5680 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5682 ocean_assert(sourcePaddingElements == 0u);
5683 ocean_assert(targetPaddingElements == 0u);
5685 typedef typename
DataType<uint8_t, 2u>::Type PixelType;
5687 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5688 const PixelType* const sourcePixelData = (const PixelType*)source;
5691 unsigned int leftOffsets[8];
5694 unsigned int topPixels[8];
5695 unsigned int bottomPixels[8];
5708 const
unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5709 const
unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5711 const
int targetOffsetX_fixed16 = (
int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5712 const
int targetOffsetY_fixed16 = (
int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5715 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5718 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5721 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5724 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5726 const
unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5727 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5729 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5731 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5733 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5734 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5735 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5737 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5739 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5741 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
5743 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
5744 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
5746 for (
unsigned int x = 0; x < targetWidth; x += 8u)
5748 if (x + 8u > targetWidth)
5753 ocean_assert(x >= 8u && targetWidth > 8u);
5754 const unsigned int newX = targetWidth - 8u;
5756 ocean_assert(x > newX);
5757 targetPixelData -= x - newX;
5762 ocean_assert(!(x + 8u < targetWidth));
5768 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
5769 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
5772 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))));
5773 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
5775 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))));
5776 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
5780 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
5781 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
5784 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
5785 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
5795 for (
unsigned int n = 0u; n < 8u; ++n)
5797 topPixels[n] = *(
unsigned int*)(sourceTopRowPixelData + leftOffsets[n]);
5800 const uint16x8_t m128_topPixels_0123 = vreinterpretq_u16_u32(vld1q_u32(topPixels + 0));
5801 const uint16x8_t m128_topPixels_4567 = vreinterpretq_u16_u32(vld1q_u32(topPixels + 4));
5803 for (
unsigned int n = 0u; n < 8u; ++n)
5805 bottomPixels[n] = *(
unsigned int*)(sourceBottomRowPixelData + leftOffsets[n]);
5808 const uint16x8_t m128_bottomPixels_0123 = vreinterpretq_u16_u32(vld1q_u32(bottomPixels + 0));
5809 const uint16x8_t m128_bottomPixels_4567 = vreinterpretq_u16_u32(vld1q_u32(bottomPixels + 4));
5816 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5817 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5820 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
5821 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
5826 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
5833 const uint16x8x2_t m2_128_topPixelsLeftRight = vuzpq_u16(m128_topPixels_0123, m128_topPixels_4567);
5839 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])));
5840 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])));
5842 const uint8x8_t& m64_topPixelsLeft_channel_0 = m2_64_topPixelsLeft_channels_01.val[0];
5843 const uint8x8_t& m64_topPixelsLeft_channel_1 = m2_64_topPixelsLeft_channels_01.val[1];
5845 const uint8x8_t& m64_topPixelsRight_channel_0 = m2_64_topPixelsRight_channels_01.val[0];
5846 const uint8x8_t& m64_topPixelsRight_channel_1 = m2_64_topPixelsRight_channels_01.val[1];
5850 uint16x8_t m128_muliplication_channel_0 = vmull_u8(m64_topPixelsLeft_channel_0, m64_u_factorsLeft);
5851 uint16x8_t m128_muliplication_channel_1 = vmull_u8(m64_topPixelsLeft_channel_1, m64_u_factorsLeft);
5853 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_topPixelsRight_channel_0, m64_u_factorsRight);
5854 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_topPixelsRight_channel_1, m64_u_factorsRight);
5856 const uint8x8_t m64_topRow_channel_0 = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5857 const uint8x8_t m64_topRow_channel_1 = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5861 const uint16x8x2_t m2_128_bottomPixelsLeftRight = vuzpq_u16(m128_bottomPixels_0123, m128_bottomPixels_4567);
5863 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])));
5864 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])));
5866 const uint8x8_t& m64_bottomPixelsLeft_channel_0 = m2_64_bottomPixelsLeft_channels_01.val[0];
5867 const uint8x8_t& m64_bottomPixelsLeft_channel_1 = m2_64_bottomPixelsLeft_channels_01.val[1];
5869 const uint8x8_t& m64_bottomPixelsRight_channel_0 = m2_64_bottomPixelsRight_channels_01.val[0];
5870 const uint8x8_t& m64_bottomPixelsRight_channel_1 = m2_64_bottomPixelsRight_channels_01.val[1];
5874 m128_muliplication_channel_0 = vmull_u8(m64_bottomPixelsLeft_channel_0, m64_u_factorsLeft);
5875 m128_muliplication_channel_1 = vmull_u8(m64_bottomPixelsLeft_channel_1, m64_u_factorsLeft);
5877 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_bottomPixelsRight_channel_0, m64_u_factorsRight);
5878 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_bottomPixelsRight_channel_1, m64_u_factorsRight);
5880 const uint8x8_t m64_bottomRow_channel_0 = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5881 const uint8x8_t m64_bottomRow_channel_1 = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5885 m128_muliplication_channel_0 = vmull_u8(m64_topRow_channel_0, m64_u_factorsTop);
5886 m128_muliplication_channel_1 = vmull_u8(m64_topRow_channel_1, m64_u_factorsTop);
5888 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_bottomRow_channel_0, m64_u_factorsBottom);
5889 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_bottomRow_channel_1, m64_u_factorsBottom);
5893 uint8x8x2_t m2_64_result;
5894 m2_64_result.val[0] = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5895 m2_64_result.val[1] = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5898 vst2_u8((uint8_t*)targetPixelData, m2_64_result);
5900 targetPixelData += 8;
5906 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
5908 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
5910 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
5912 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
5913 ocean_assert(lastSourcePixelLeft < sourceWidth);
5914 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
5916 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
5918 const unsigned int factorRight = factorRight_fixed16 >> 9u;
5919 const unsigned int factorLeft = 128u - factorRight;
5921 for (
unsigned int c = 0u; c < 2u; ++c)
5923 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
5924 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
5932#ifdef OCEAN_WE_KEEP_THIS_IMPLEMENTATION_AS_WE_NEED_THIS_TO_FOR_A_NEW_NEON_IMPLEMENTATION
5935inline 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)
5937 ocean_assert(source !=
nullptr && target !=
nullptr);
5938 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5939 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
5940 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
5941 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5942 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5944 ocean_assert(sourcePaddingElements == 0u);
5945 ocean_assert(targetPaddingElements == 0u);
5947 typedef typename DataType<uint8_t, 3u>::Type PixelType;
5949 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5950 const PixelType*
const sourcePixelData = (
const PixelType*)source;
5953 unsigned int leftOffsets[8];
5966 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5967 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5969 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5970 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5973 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5976 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5979 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5982 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5984 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5985 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5987 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5989 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5991 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5992 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5993 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5995 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5997 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5999 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6001 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
6002 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6004 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6006 if (x + 8u > targetWidth)
6011 ocean_assert(x >= 8u && targetWidth > 8u);
6012 const unsigned int newX = targetWidth - 8u;
6014 ocean_assert(x > newX);
6015 targetPixelData -= x - newX;
6020 ocean_assert(!(x + 8u < targetWidth));
6026 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6027 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6030 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))));
6031 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6033 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))));
6034 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6038 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6039 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6042 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6043 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6050 uint8x8x3_t topLeftPixels;
6051 uint8x8x3_t topRightPixels;
6053 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
6054 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
6056 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
6057 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
6059 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
6060 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
6062 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
6063 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
6065 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
6066 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
6068 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
6069 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
6071 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
6072 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
6074 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
6075 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
6080 uint8x8x3_t bottomLeftPixels;
6081 uint8x8x3_t bottomRightPixels;
6083 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
6084 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
6086 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
6087 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
6089 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
6090 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
6092 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
6093 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
6095 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
6096 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
6098 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
6099 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
6101 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
6102 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
6104 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
6105 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
6113 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6114 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6117 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6118 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6119 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6124 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
6125 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
6126 uint16x8_t m128_muliplicationChannel_2 = vmull_u8(topLeftPixels.val[2], m64_u_factorsLeft);
6128 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
6129 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
6130 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, topRightPixels.val[2], m64_u_factorsRight);
6132 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6133 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6134 uint8x8_t m64_topRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6139 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
6140 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
6141 m128_muliplicationChannel_2 = vmull_u8(bottomLeftPixels.val[2], m64_u_factorsLeft);
6143 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
6144 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
6145 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, bottomRightPixels.val[2], m64_u_factorsRight);
6147 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6148 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6149 uint8x8_t m64_bottomRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6154 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
6155 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
6156 m128_muliplicationChannel_2 = vmull_u8(m64_topRowChannel_2, m64_u_factorsTop);
6158 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
6159 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
6160 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, m64_bottomRowChannel_2, m64_u_factorsBottom);
6165 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6166 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6167 result.val[2] = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6170 vst3_u8((uint8_t*)targetPixelData, result);
6172 targetPixelData += 8;
6178 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6180 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6182 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6184 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6185 ocean_assert(lastSourcePixelLeft < sourceWidth);
6186 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6188 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6190 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6191 const unsigned int factorLeft = 128u - factorRight;
6193 for (
unsigned int c = 0u; c < 3u; ++c)
6195 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
6196 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6204#ifdef OCEAN_WE_KEEP_ALSO_THIS_SLOW_IMPLEMENTATION_SHOWING_A_MORE_GENERIC_APPROACH
6209inline 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)
6211 ocean_assert(source !=
nullptr && target !=
nullptr);
6212 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
6213 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
6214 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
6215 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
6216 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6218 ocean_assert(sourcePaddingElements == 0u);
6219 ocean_assert(targetPaddingElements == 0u);
6221 typedef typename DataType<uint8_t, 4u>::Type PixelType;
6223 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
6224 const PixelType*
const sourcePixelData = (
const PixelType*)source;
6227 unsigned int leftOffsets[8];
6230 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6243 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
6244 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6246 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
6247 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
6250 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
6253 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
6256 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
6259 const int32x4_t m128_s_zero = vdupq_n_s32(0);
6261 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
6262 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
6264 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6266 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
6268 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
6269 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
6270 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
6272 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
6274 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
6276 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6278 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
6279 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6281 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6283 if (x + 8u > targetWidth)
6288 ocean_assert(x >= 8u && targetWidth > 8u);
6289 const unsigned int newX = targetWidth - 8u;
6291 ocean_assert(x > newX);
6292 targetPixelData -= x - newX;
6297 ocean_assert(!(x + 8u < targetWidth));
6303 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6304 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6307 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))));
6308 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6310 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))));
6311 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6315 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6316 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6319 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6320 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6327 uint8x8x4_t topLeftPixels;
6328 uint8x8x4_t topRightPixels;
6330 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
6331 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
6333 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
6334 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
6336 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
6337 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
6339 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
6340 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
6342 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
6343 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
6345 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
6346 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
6348 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
6349 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
6351 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
6352 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
6357 uint8x8x4_t bottomLeftPixels;
6358 uint8x8x4_t bottomRightPixels;
6360 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
6361 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
6363 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
6364 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
6366 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
6367 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
6369 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
6370 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
6372 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
6373 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
6375 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
6376 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
6378 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
6379 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
6381 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
6382 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
6390 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6391 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6394 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6395 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6396 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6401 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
6402 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
6403 uint16x8_t m128_muliplicationChannel_2 = vmull_u8(topLeftPixels.val[2], m64_u_factorsLeft);
6404 uint16x8_t m128_muliplicationChannel_3 = vmull_u8(topLeftPixels.val[3], m64_u_factorsLeft);
6406 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
6407 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
6408 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, topRightPixels.val[2], m64_u_factorsRight);
6409 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, topRightPixels.val[3], m64_u_factorsRight);
6411 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6412 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6413 uint8x8_t m64_topRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6414 uint8x8_t m64_topRowChannel_3 = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6419 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
6420 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
6421 m128_muliplicationChannel_2 = vmull_u8(bottomLeftPixels.val[2], m64_u_factorsLeft);
6422 m128_muliplicationChannel_3 = vmull_u8(bottomLeftPixels.val[3], m64_u_factorsLeft);
6424 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
6425 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
6426 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, bottomRightPixels.val[2], m64_u_factorsRight);
6427 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, bottomRightPixels.val[3], m64_u_factorsRight);
6429 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6430 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6431 uint8x8_t m64_bottomRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6432 uint8x8_t m64_bottomRowChannel_3 = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6437 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
6438 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
6439 m128_muliplicationChannel_2 = vmull_u8(m64_topRowChannel_2, m64_u_factorsTop);
6440 m128_muliplicationChannel_3 = vmull_u8(m64_topRowChannel_3, m64_u_factorsTop);
6442 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
6443 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
6444 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, m64_bottomRowChannel_2, m64_u_factorsBottom);
6445 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, m64_bottomRowChannel_3, m64_u_factorsBottom);
6450 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6451 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6452 result.val[2] = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6453 result.val[3] = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6456 vst4_u8((uint8_t*)targetPixelData, result);
6458 targetPixelData += 8;
6464 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6466 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6468 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6470 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6471 ocean_assert(lastSourcePixelLeft < sourceWidth);
6472 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6474 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6476 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6477 const unsigned int factorLeft = 128u - factorRight;
6479 for (
unsigned int c = 0u; c < 4u; ++c)
6481 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorTop
6482 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6493inline void FrameInterpolatorBilinear::interpolateRowVerticalNEON<float>(
const float* sourceRowTop,
const float* sourceRowBottom,
float* targetRow,
const unsigned int elements,
const float factorBottom)
6495 ocean_assert(sourceRowTop !=
nullptr);
6496 ocean_assert(sourceRowBottom !=
nullptr);
6497 ocean_assert(targetRow !=
nullptr);
6498 ocean_assert(elements >= 16u);
6499 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
6502 const float32x4_t constant_1_f_32x4 = vdupq_n_f32(1.0f);
6504 const float32x4_t factorsBottom_f_32x4 = vdupq_n_f32(factorBottom);
6505 const float32x4_t factorsTop_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsBottom_f_32x4);
6507 for (
unsigned int n = 0u; n < elements; n += 16u)
6509 if (n + 16u > elements)
6514 ocean_assert(n >= 16u && elements > 16u);
6515 const unsigned int offset = n - (elements - 16u);
6516 ocean_assert(offset < 16u);
6518 sourceRowTop -= offset;
6519 sourceRowBottom -= offset;
6520 targetRow -= offset;
6523 ocean_assert(!(n + 16u < elements));
6527 const float32x4_t top_03_32x4 = vld1q_f32(sourceRowTop + 0);
6528 const float32x4_t top_47_32x4 = vld1q_f32(sourceRowTop + 4);
6529 const float32x4_t top_8B_32x4 = vld1q_f32(sourceRowTop + 8);
6530 const float32x4_t top_CF_32x4 = vld1q_f32(sourceRowTop + 12);
6532 const float32x4_t bottom_03_32x4 = vld1q_f32(sourceRowBottom + 0);
6533 const float32x4_t bottom_47_32x4 = vld1q_f32(sourceRowBottom + 4);
6534 const float32x4_t bottom_8B_32x4 = vld1q_f32(sourceRowBottom + 8);
6535 const float32x4_t bottom_CF_32x4 = vld1q_f32(sourceRowBottom + 12);
6538 float32x4_t interpolatedRow_03_32x4 = vmulq_f32(top_03_32x4, factorsTop_f_32x4);
6539 float32x4_t interpolatedRow_47_32x4 = vmulq_f32(top_47_32x4, factorsTop_f_32x4);
6540 float32x4_t interpolatedRow_8B_32x4 = vmulq_f32(top_8B_32x4, factorsTop_f_32x4);
6541 float32x4_t interpolatedRow_CF_32x4 = vmulq_f32(top_CF_32x4, factorsTop_f_32x4);
6543 interpolatedRow_03_32x4 = vmlaq_f32(interpolatedRow_03_32x4, bottom_03_32x4, factorsBottom_f_32x4);
6544 interpolatedRow_47_32x4 = vmlaq_f32(interpolatedRow_47_32x4, bottom_47_32x4, factorsBottom_f_32x4);
6545 interpolatedRow_8B_32x4 = vmlaq_f32(interpolatedRow_8B_32x4, bottom_8B_32x4, factorsBottom_f_32x4);
6546 interpolatedRow_CF_32x4 = vmlaq_f32(interpolatedRow_CF_32x4, bottom_CF_32x4, factorsBottom_f_32x4);
6549 vst1q_f32(targetRow + 0, interpolatedRow_03_32x4);
6550 vst1q_f32(targetRow + 4, interpolatedRow_47_32x4);
6551 vst1q_f32(targetRow + 8, interpolatedRow_8B_32x4);
6552 vst1q_f32(targetRow + 12, interpolatedRow_CF_32x4);
6555 sourceRowBottom += 16;
6561inline 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)
6563 ocean_assert(extendedSourceRow !=
nullptr);
6564 ocean_assert(targetRow !=
nullptr);
6565 ocean_assert(targetWidth >= 8u);
6566 ocean_assert(interpolationLocations !=
nullptr);
6567 ocean_assert(interpolationFactorsRight !=
nullptr);
6569 ocean_assert(channels == 1u);
6572 const float32x4_t constant_1_f_32x4 = vdupq_n_f32(1.0f);
6574 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6576 if (x + 8u > targetWidth)
6581 ocean_assert(x >= 8u && targetWidth > 8u);
6582 const unsigned int newX = targetWidth - 8u;
6584 ocean_assert(x > newX);
6585 const unsigned int offset = x - newX;
6587 targetRow -= offset;
6588 interpolationLocations -= offset;
6589 interpolationFactorsRight -= offset;
6594 ocean_assert(!(x + 8u < targetWidth));
6599 const float32x2_t pixel_0_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[0]);
6600 const float32x2_t pixel_1_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[1]);
6601 const float32x4_t pixel_01_f_32x4 = vcombine_f32(pixel_0_f_32x2, pixel_1_f_32x2);
6603 const float32x2_t pixel_2_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[2]);
6604 const float32x2_t pixel_3_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[3]);
6605 const float32x4_t pixel_23_f_32x4 = vcombine_f32(pixel_2_f_32x2, pixel_3_f_32x2);
6607 const float32x2_t pixel_4_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[4]);
6608 const float32x2_t pixel_5_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[5]);
6609 const float32x4_t pixel_45_f_32x4 = vcombine_f32(pixel_4_f_32x2, pixel_5_f_32x2);
6611 const float32x2_t pixel_6_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[6]);
6612 const float32x2_t pixel_7_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[7]);
6613 const float32x4_t pixel_67_f_32x4 = vcombine_f32(pixel_6_f_32x2, pixel_7_f_32x2);
6615 const float32x4_t factorsRight_0123_f_32x4 = vld1q_f32(interpolationFactorsRight + 0);
6616 const float32x4_t factorsLeft_0123_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsRight_0123_f_32x4);
6617 const float32x4x2_t factorsLeftRight_0123_f_32x4_2 = vzipq_f32(factorsLeft_0123_f_32x4, factorsRight_0123_f_32x4);
6619 const float32x4_t factorsRight_4567_f_32x4 = vld1q_f32(interpolationFactorsRight + 4);
6620 const float32x4_t factorsLeft_4567_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsRight_4567_f_32x4);
6621 const float32x4x2_t factorsLeftRight_4567_f_32x4_2 = vzipq_f32(factorsLeft_4567_f_32x4, factorsRight_4567_f_32x4);
6623 const float32x4_t multiplied_01_f_32x4 = vmulq_f32(pixel_01_f_32x4, factorsLeftRight_0123_f_32x4_2.val[0]);
6624 const float32x4_t multiplied_23_f_32x4 = vmulq_f32(pixel_23_f_32x4, factorsLeftRight_0123_f_32x4_2.val[1]);
6626 const float32x4_t multiplied_45_f_32x4 = vmulq_f32(pixel_45_f_32x4, factorsLeftRight_4567_f_32x4_2.val[0]);
6627 const float32x4_t multiplied_67_f_32x4 = vmulq_f32(pixel_67_f_32x4, factorsLeftRight_4567_f_32x4_2.val[1]);
6629 const float32x2_t result_01_f_32x2 = vpadd_f32(vget_low_f32(multiplied_01_f_32x4), vget_high_f32(multiplied_01_f_32x4));
6630 const float32x2_t result_23_f_32x2 = vpadd_f32(vget_low_f32(multiplied_23_f_32x4), vget_high_f32(multiplied_23_f_32x4));
6632 const float32x2_t result_45_f_32x2 = vpadd_f32(vget_low_f32(multiplied_45_f_32x4), vget_high_f32(multiplied_45_f_32x4));
6633 const float32x2_t result_67_f_32x2 = vpadd_f32(vget_low_f32(multiplied_67_f_32x4), vget_high_f32(multiplied_67_f_32x4));
6635 const float32x4_t result_0123_f_32x4 = vcombine_f32(result_01_f_32x2, result_23_f_32x2);
6636 const float32x4_t result_4567_f_32x4 = vcombine_f32(result_45_f_32x2, result_67_f_32x2);
6638 vst1q_f32(targetRow + 0, result_0123_f_32x4);
6639 vst1q_f32(targetRow + 4, result_4567_f_32x4);
6642 interpolationLocations += 8;
6643 interpolationFactorsRight += 8;
6648inline 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)
6650 ocean_assert(source !=
nullptr && target !=
nullptr);
6651 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
6652 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
6653 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6655 ocean_assert(sourceWidth != targetWidth || sourceHeight != targetHeight);
6657 const unsigned int sourceStrideElements = sourceWidth * 1u + sourcePaddingElements;
6658 const unsigned int targetStrideElements = targetWidth * 1u + targetPaddingElements;
6660 typedef void (*InterpolateRowVerticalFunction)(
const float*,
const float*,
float*,
const unsigned int,
const float);
6661 typedef void (*InterpolateRowHorizontalFunction)(
const float*,
float*,
const unsigned int,
const unsigned int,
const unsigned int*,
const float*);
6663 InterpolateRowVerticalFunction interpolateRowVerticalFunction = interpolateRowVertical<float>;
6664 InterpolateRowHorizontalFunction interpolateRowHorizontalFunction = interpolateRowHorizontal<float, 1u>;
6666 if (sourceWidth * 1u >= 16u)
6668 interpolateRowVerticalFunction = interpolateRowVerticalNEON<float>;
6671 if (targetWidth >= 8u)
6673 interpolateRowHorizontalFunction = interpolateRowHorizontalNEON<float, 1u>;
6676 target += targetStrideElements * firstTargetRow;
6678 const float sourceX_T_targetX = float(sourceX_s_targetX);
6679 const float sourceY_T_targetY = float(sourceY_s_targetY);
6683 Memory memoryIntermediateExtendedRow;
6684 Memory memoryHorizontalInterpolationLocations;
6685 Memory memoryHorizontalInterpolationFactorsRight;
6687 if (sourceWidth != targetWidth)
6691 memoryIntermediateExtendedRow = Memory::create<float>(sourceWidth + 1u);
6693 memoryHorizontalInterpolationLocations = Memory::create<unsigned int>(targetWidth);
6695 memoryHorizontalInterpolationFactorsRight = Memory::create<float>(targetWidth);
6698 if (memoryHorizontalInterpolationLocations)
6700 ocean_assert(memoryHorizontalInterpolationFactorsRight);
6702 if (targetWidth >= 4u)
6704 const float32x4_t sourceX_T_targetX_f_32x4 = vdupq_n_f32(sourceX_T_targetX);
6705 const float32x4_t targetOffsetX_f_32x4 = vdupq_n_f32(sourceX_T_targetX * 0.5f - 0.5f);
6708 const float32x4_t constant_0_f_32x4 = vdupq_n_f32(0);
6711 const float32x4_t constant_4_f_32x4 = vdupq_n_f32(4.0f);
6714 const uint32x4_t sourceWidth_1_u_32x4 = vdupq_n_u32(sourceWidth - 1u);
6717 const float f_0123[4] = {0.0f, 1.0f, 2.0f, 3.0f};
6718 float32x4_t x_0123_f_32x4 = vld1q_f32(f_0123);
6722 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
6724 if (x + 4u > targetWidth)
6729 ocean_assert(x >= 4u && targetWidth > 4u);
6730 const unsigned int newX = targetWidth - 4u;
6732 ocean_assert(x > newX);
6733 const unsigned int offset = x - newX;
6737 x_0123_f_32x4 = vsubq_f32(x_0123_f_32x4, vdupq_n_f32(
float(offset)));
6740 ocean_assert(!(x + 4u < targetWidth));
6744 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)));
6748 uint32x4_t left_0123_u_32x4 = vminq_u32(vcvtq_u32_f32(sourceX_0123_f_32x4), sourceWidth_1_u_32x4);
6751 vst1q_u32(memoryHorizontalInterpolationLocations.
data<
unsigned int>() + x, left_0123_u_32x4);
6754 const float32x4_t factorsRight_f_32x4 = vsubq_f32(sourceX_0123_f_32x4, vcvtq_f32_u32(left_0123_u_32x4));
6756 vst1q_f32(memoryHorizontalInterpolationFactorsRight.
data<
float>() + x, factorsRight_f_32x4);
6759 x_0123_f_32x4 = vaddq_f32(x_0123_f_32x4, constant_4_f_32x4);
6764 const float targetOffsetX = sourceX_T_targetX * 0.5f - 0.5f;
6768 for (
unsigned int x = 0u; x < targetWidth; ++x)
6770 const float sourceX = max(0.0f, targetOffsetX +
float(x) * sourceX_T_targetX);
6772 const unsigned int left = min((
unsigned int)sourceX, sourceWidth - 1u);
6774 memoryHorizontalInterpolationLocations.
data<
unsigned int>()[x] = left;
6776 const float factorRight = sourceX - float(left);
6777 ocean_assert(factorRight >= 0.0f && factorRight <= 1.0f);
6779 memoryHorizontalInterpolationFactorsRight.
data<
float>()[x] = factorRight;
6784 const float targetOffsetY = sourceY_T_targetY * 0.5f - 0.5f;
6786 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6788 const float sourceY = minmax<float>(0.0f, targetOffsetY + sourceY_T_targetY *
float(y),
float(sourceHeight) - 1.0f);
6790 const unsigned int sourceRowTop = (
unsigned int)sourceY;
6791 const float factorBottom = sourceY - float(sourceRowTop);
6792 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
6794 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6796 const float*
const sourceTopRow = source + sourceStrideElements * sourceRowTop;
6797 const float*
const sourceBottomRow = source + sourceStrideElements * sourceRowBottom;
6799 float* targetRow =
nullptr;
6801 if (sourceHeight == targetHeight)
6803 ocean_assert(sourceWidth != targetWidth);
6804 ocean_assert(memoryIntermediateExtendedRow);
6807 memcpy(memoryIntermediateExtendedRow.
data<
float>(), sourceTopRow, sourceWidth *
sizeof(
float));
6812 targetRow = memoryIntermediateExtendedRow.
isNull() ? target : memoryIntermediateExtendedRow.
data<
float>();
6814 ocean_assert(targetRow !=
nullptr);
6815 ocean_assert(interpolateRowVerticalFunction !=
nullptr);
6816 interpolateRowVerticalFunction(sourceTopRow, sourceBottomRow, targetRow, sourceWidth * 1u, factorBottom);
6819 if (memoryIntermediateExtendedRow)
6823 memoryIntermediateExtendedRow.
data<
float>()[sourceWidth] = memoryIntermediateExtendedRow.
data<
float>()[sourceWidth - 1u];
6825 interpolateRowHorizontalFunction(memoryIntermediateExtendedRow.
data<
float>(), target, targetWidth, 1u, memoryHorizontalInterpolationLocations.
data<
unsigned int>(), memoryHorizontalInterpolationFactorsRight.
data<
float>());
6828 target += targetStrideElements;
6834template <
typename T,
typename TScale,
unsigned int tChannels>
6835void 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)
6837 static_assert((std::is_same<float, TScale>::value || std::is_same<double, TScale>::value),
"Invalid TScale type");
6839 ocean_assert(source !=
nullptr && target !=
nullptr);
6840 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
6841 ocean_assert_and_suppress_unused(targetWidth >= 1u && targetHeight >= 1u, targetHeight);
6842 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6844 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
6845 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
6847 const TScale sourceX_T_targetX = TScale(sourceX_s_targetX);
6848 const TScale sourceY_T_targetY = TScale(sourceY_s_targetY);
6896 const TScale sourceX_T_targetXOffset = sourceX_T_targetX * TScale(0.5) - TScale(0.5);
6897 const TScale sourceY_T_targetYOffset = sourceY_T_targetY * TScale(0.5) - TScale(0.5);
6899 const TScale sourceWidth_1 = TScale(sourceWidth - 1u);
6900 const TScale sourceHeight_1 = TScale(sourceHeight - 1u);
6902 target += targetStrideElements * firstTargetRow;
6904 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6906 const TScale sy =
minmax(TScale(0), sourceY_T_targetYOffset + sourceY_T_targetY * TScale(y), sourceHeight_1);
6907 ocean_assert(sy >= TScale(0) && sy < TScale(sourceHeight));
6909 const unsigned int sTop = (
unsigned int)sy;
6910 ocean_assert(sy >= TScale(sTop));
6912 const TScale factorBottom = sy - TScale(sTop);
6913 ocean_assert(factorBottom >= TScale(0) && factorBottom <= TScale(1));
6915 const TScale factorTop = TScale(1) - factorBottom;
6916 ocean_assert(factorTop >= TScale(0) && factorTop <= TScale(1));
6918 const T*
const sourceTop = source + sTop * sourceStrideElements;
6919 const T*
const sourceBottom = (sTop + 1u < sourceHeight) ? sourceTop + sourceStrideElements : sourceTop;
6921 for (
unsigned int x = 0; x < targetWidth; ++x)
6923 const TScale sx =
minmax(TScale(0), sourceX_T_targetXOffset + sourceX_T_targetX * TScale(x), sourceWidth_1);
6924 ocean_assert(sx >= TScale(0) && sx < TScale(sourceWidth));
6926 const unsigned int sLeft = (
unsigned int)sx;
6927 ocean_assert(sx >= TScale(sLeft));
6929 const TScale factorRight = sx - TScale(sLeft);
6930 ocean_assert(factorRight >= TScale(0) && factorRight <= TScale(1));
6932 const TScale factorLeft = TScale(1) - factorRight;
6933 ocean_assert(factorLeft >= TScale(0) && factorLeft <= TScale(1));
6935 const unsigned int sourceRightOffset = sLeft + 1u < sourceWidth ? tChannels : 0u;
6937 const T*
const sourceTopLeft = sourceTop + sLeft * tChannels;
6938 const T*
const sourceBottomLeft = sourceBottom + sLeft * tChannels;
6940 const TScale factorTopLeft = factorTop * factorLeft;
6941 const TScale factorTopRight = factorTop * factorRight;
6942 const TScale factorBottomLeft = factorBottom * factorLeft;
6943 const TScale factorBottomRight = factorBottom * factorRight;
6945 for (
unsigned int n = 0u; n < tChannels; ++n)
6947 target[n] = T(TScale(sourceTopLeft[n]) * factorTopLeft + TScale(sourceTopLeft[sourceRightOffset + n]) * factorTopRight
6948 + TScale(sourceBottomLeft[n]) * factorBottomLeft + TScale(sourceBottomLeft[sourceRightOffset + n]) * factorBottomRight);
6951 target += tChannels;
6954 target += targetPaddingElements;
6958template <
unsigned int tChannels>
6959void 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)
6961 static_assert(tChannels != 0u,
"Invalid channel number!");
6963 ocean_assert(firstTargetRow + numberTargetRows <= height);
6967 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
6969 uint8_t zeroColor[tChannels] = {uint8_t(0)};
6970 const PixelType bColor = borderColor ? *(
const PixelType*)borderColor : *(
const PixelType*)zeroColor;
6973 const SquareMatrix2 rotationMatrix2(rotationMatrix3(0, 0), rotationMatrix3(1, 0), rotationMatrix3(0, 1), rotationMatrix3(1, 1));
6977 const Vector2 anchorPosition(horizontalAnchorPosition, verticalAnchorPosition);
6979 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6981 PixelType* targetPixel = (PixelType*)(target + y * targetStrideElements);
6985 for (
unsigned int x = 0; x < width; ++x)
6987 const Vector2 sourceLocation(anchorPosition + rotationMatrix2 * (
Vector2(
Scalar(x), floatY) - anchorPosition));
6989 if (sourceLocation.
x() >= 0 && sourceLocation.
y() >= 0 && sourceLocation.
x() <= width_1 && sourceLocation.
y() <= height_1)
6991 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(source, width, height, sourcePaddingElements, sourceLocation, (uint8_t*)(targetPixel));
6995 *targetPixel = bColor;
This class implements the abstract base class for all AnyCamera objects.
Definition AnyCamera.h:130
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:1160
The following comfort class provides comfortable functions simplifying prototyping applications but a...
Definition FrameInterpolatorBilinear.h:60
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:1524
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:1437
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:341
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:44
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:4288
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:1736
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:1896
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:1802
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:1836
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:1963
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:2467
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:1819
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:4510
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:1789
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:3580
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:2383
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:1773
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:3960
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:4354
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:4590
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:1660
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:4636
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:3330
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:4995
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:5410
LookupCorner2< Vector2 > LookupTable
Definition of a lookup table for 2D vectors.
Definition FrameInterpolatorBilinear.h:50
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:5375
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:6959
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:1883
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:3262
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:1760
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:4684
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:1611
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:1624
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:4738
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:5234
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:1945
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:5355
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:1698
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:2142
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:5137
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:2231
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:2652
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:5190
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:4435
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:6835
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:2306
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:2056
This class implements a 2D pixel position with pixel precision.
Definition PixelPosition.h:65
T y() const
Returns the vertical coordinate position of this object.
Definition PixelPosition.h:470
T x() const
Returns the horizontal coordinate position of this object.
Definition PixelPosition.h:458
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:3770
static Caller< void > createStatic(typename StaticFunctionPointerMaker< void, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass, NullClass >::Type function)
Creates a new caller container for a static function with no function parameter.
Definition Caller.h:2876
Template class allowing to define an array of data types.
Definition DataType.h:27
This class implements Ocean's image class.
Definition Frame.h:1808
void setRelativeTimestamp(const Timestamp &relative)
Sets the relative timestamp of this frame.
Definition Frame.h:4233
bool isValid() const
Returns whether this frame is valid.
Definition Frame.h:4528
void setTimestamp(const Timestamp ×tamp)
Sets the timestamp of this frame.
Definition Frame.h:4228
const Timestamp & timestamp() const
Returns the timestamp of this frame.
Definition Frame.h:4218
const Timestamp & relativeTimestamp() const
Returns the relative timestamp of this frame.
Definition Frame.h:4223
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:2026
static constexpr bool isEqualEps(const T value)
Returns whether a value is smaller than or equal to a small epsilon.
Definition Numeric.h:2087
static constexpr bool isNotEqualEps(const T value)
Returns whether a value is not smaller than or equal to a small epsilon.
Definition Numeric.h:2237
unsigned int width() const
Returns the width of the camera image.
Definition PinholeCamera.h:1300
const SquareMatrixT3< T > & invertedIntrinsic() const
Returns the inverted intrinsic camera matrix.
Definition PinholeCamera.h:1263
const SquareMatrixT3< T > & intrinsic() const
Returns the intrinsic camera matrix.
Definition PinholeCamera.h:1257
unsigned int height() const
Returns the height of the camera image.
Definition PinholeCamera.h:1306
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:1602
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:1333
const T * data() const
Returns a pointer to the internal values.
Definition SquareMatrix3.h:1046
bool isOrthonormal(const T epsilon=NumericT< T >::eps()) const
Returns whether this matrix is an orthonormal matrix.
Definition SquareMatrix3.h:1365
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:903
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
SquareMatrixT3< Scalar > SquareMatrix3
Definition of the SquareMatrix3 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with ...
Definition SquareMatrix3.h:42
RotationT< Scalar > Rotation
Definition of the Rotation object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION flag either with ...
Definition Rotation.h:38
float Scalar
Definition of a scalar type.
Definition Math.h:129
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition Vector3.h:29
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition Vector2.h:28
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