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))
1429 frame = std::move(target);
1433 template <
typename TScalar>
1436 ocean_assert(frame !=
nullptr);
1437 ocean_assert(channels >= 1u && channels <= 8u);
1444 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<1u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1448 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<2u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1452 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<3u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1456 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<4u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1460 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<5u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1464 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<6u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1468 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<7u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1472 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<8u, PC_TOP_LEFT, TScalar>(frame, width, height, framePaddingElements, position, result);
1483 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<1u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1487 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<2u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1491 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<3u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1495 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<4u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1499 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<5u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1503 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<6u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1507 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<7u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1511 FrameInterpolatorBilinear::interpolatePixel8BitPerChannel<8u, PC_CENTER, TScalar>(frame, width, height, framePaddingElements, position, result);
1516 ocean_assert(
false &&
"Invalid channel number");
1520 template <
typename TSource,
typename TTarget,
typename TScalar,
typename TIntermediate>
1523 ocean_assert(frame !=
nullptr);
1524 ocean_assert(channels >= 1u && channels <= 8u);
1531 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 1u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1535 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 2u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1539 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 3u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1543 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 4u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1547 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 5u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1551 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 6u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1555 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 7u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1559 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 8u, PC_TOP_LEFT, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1570 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 1u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1574 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 2u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1578 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 3u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1582 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 4u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1586 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 5u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1590 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 6u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1594 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 7u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1598 FrameInterpolatorBilinear::interpolatePixel<TSource, TTarget, 8u, PC_CENTER, TScalar, TIntermediate>(frame, width, height, framePaddingElements, position, result, resultBias);
1603 ocean_assert(
false &&
"Invalid channel number");
1607 template <
typename T,
unsigned int tChannels>
1608 inline 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)
1610 ocean_assert(source !=
nullptr && target !=
nullptr);
1611 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
1612 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
1614 const double sourceX_s_targetX = double(sourceWidth) / double(targetWidth);
1615 const double sourceY_s_targetY = double(sourceHeight) / double(targetHeight);
1617 scale<T, tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, worker);
1620 template <
typename T,
unsigned int tChannels>
1621 inline 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)
1623 ocean_assert(source !=
nullptr && target !=
nullptr);
1624 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
1625 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
1626 ocean_assert(sourceX_s_targetX > 0.0);
1627 ocean_assert(sourceY_s_targetY > 0.0);
1629 if (sourceWidth == targetWidth && sourceHeight == targetHeight)
1631 FrameConverter::subFrame<T>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, 0u, 0u, 0u, 0u, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements);
1635 if (std::is_same<T, uint8_t>::value)
1639 scale8BitPerChannel<tChannels>((
const uint8_t*)source, (uint8_t*)target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, worker);
1647 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);
1651 scaleSubset<T, TScale, tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
1656 template <
unsigned int tChannels>
1657 inline 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)
1664 if (targetWidth >= 4u)
1666 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1667 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);
1669 #elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1670 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);
1675 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);
1679 if (targetWidth >= 4u)
1681 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1682 affine8BitPerChannelSSESubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1684 #elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1685 affine8BitPerChannelNEONSubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1690 affine8BitPerChannelSubset<tChannels>(source, sourceWidth, sourceHeight, &adjustedAffineTransform, borderColor, target, targetWidth, targetHeight, 0u, targetHeight, sourcePaddingElements, targetPaddingElements);
1694 template <
unsigned int tChannels>
1695 inline 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)
1702 if (outputWidth >= 4u)
1704 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1705 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);
1707 #elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1708 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);
1713 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);
1717 if (outputWidth >= 4u)
1719 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
1720 homography8BitPerChannelSSESubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1722 #elif defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1723 homography8BitPerChannelNEONSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1728 homography8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1732 template <
typename T,
unsigned int tChannels>
1733 inline 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)
1735 if (std::is_same<T, uint8_t>::value)
1737 homography8BitPerChannel<tChannels>((
const uint8_t*)input, inputWidth, inputHeight, input_H_output, (
const uint8_t*)borderColor, (uint8_t*)output, outputOrigin, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, worker);
1747 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);
1751 homographySubset<T, tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, borderColor, output, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1756 template <
unsigned int tChannels>
1757 inline 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)
1761 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);
1765 homographies8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, homographies, borderColor, output, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, 0u, outputHeight);
1769 template <
unsigned int tChannels>
1770 inline 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)
1777 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);
1781 homographyMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_H_shiftedOutput, output, outputMask, maskValue, outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, outputHeight);
1785 template <
unsigned int tChannels>
1786 inline 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)
1790 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);
1794 homographiesMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, homographies, output, outputMask, maskValue, outputQuadrantCenter.
x(), outputQuadrantCenter.
y(), outputOrigin.
x(), outputOrigin.
y(), outputWidth, outputHeight, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, outputHeight);
1798 template <
unsigned int tChannels>
1803 const PinholeCamera::DistortionLookup outputCameraDistortionLookup(outputCamera, 10u);
1807 worker->
executeFunction(
Worker::Function::createStatic(&FrameInterpolatorBilinear::homographyWithCamera8BitPerChannelSubset<tChannels>, &inputCamera, &outputCamera, &outputCameraDistortionLookup, input, &normalizedHomography, useDistortionParameters, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, 0u), 0, outputCamera.
height());
1811 homographyWithCamera8BitPerChannelSubset<tChannels>(&inputCamera, &outputCamera, &outputCameraDistortionLookup, input, &normalizedHomography, useDistortionParameters, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, outputCamera.
height());
1815 template <
unsigned int tChannels>
1816 inline 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)
1820 const PinholeCamera::DistortionLookup outputCameraDistortionLookup(outputCamera, 10u);
1824 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);
1828 homographyWithCameraMask8BitPerChannelSubset<tChannels>(&inputCamera, &outputCamera, &outputCameraDistortionLookup, input, inputPaddingElements, &normalizedHomography, output, outputMask, outputPaddingElements, outputMaskPaddingElements, maskValue, 0u, outputCamera.
height());
1832 template <
typename T,
unsigned int tChannels>
1833 inline 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)
1835 if constexpr (std::is_same<T, uint8_t>::value)
1837 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
1838 if ((tChannels >= 1u && input_LT_output.
sizeX() >= 8) || (tChannels >= 2u && input_LT_output.
sizeX() >= 4))
1844 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);
1848 lookup8BitPerChannelSubsetNEON<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1857 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);
1861 lookup8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1866 ocean_assert((!std::is_same<T, uint8_t>::value));
1870 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);
1874 lookupSubset<T, tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, borderColor, output, inputPaddingElements, outputPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1879 template <
unsigned int tChannels>
1880 inline 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)
1884 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);
1888 lookupMask8BitPerChannelSubset<tChannels>(input, inputWidth, inputHeight, &input_LT_output, offset, output, outputMask, maskValue, inputPaddingElements, outputPaddingElements, outputMaskPaddingElements, 0u, (
unsigned int)(input_LT_output.
sizeY()));
1892 template <
typename T,
unsigned int tChannels>
1893 void 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)
1895 static_assert(tChannels >= 1u,
"Invalid channel number!");
1897 ocean_assert(sourceFrame !=
nullptr);
1898 ocean_assert(sourceCamera.
isValid());
1900 ocean_assert(targetCamera.
isValid());
1901 ocean_assert(targetFrame !=
nullptr);
1902 ocean_assert(binSizeInPixel >= 1u);
1904 const size_t binsX = std::max(1u, targetCamera.
width() / binSizeInPixel);
1905 const size_t binsY = std::max(1u, targetCamera.
height() / binSizeInPixel);
1908 for (
size_t yBin = 0; yBin <= lookupTable.
binsY(); ++yBin)
1910 for (
size_t xBin = 0; xBin <= lookupTable.
binsX(); ++xBin)
1914 constexpr
bool makeUnitVector =
false;
1916 const Vector3 rayI = source_R_target * targetCamera.
vector(cornerPosition, makeUnitVector);
1933 lookup<T, tChannels>(sourceFrame, sourceCamera.
width(), sourceCamera.
height(), lookupTable,
true , borderColor, targetFrame, sourceFramePaddingElements, targetFramePaddingElements, worker);
1935 if (source_OLT_target)
1937 *source_OLT_target = std::move(lookupTable);
1941 template <
unsigned int tChannels>
1942 void 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)
1944 static_assert(tChannels != 0u,
"Invalid channel number!");
1946 ocean_assert(source !=
nullptr && target !=
nullptr);
1947 ocean_assert(width >= 1u && height >= 1u);
1951 worker->
executeFunction(
Worker::Function::createStatic(&rotate8BitPerChannelSubset<tChannels>, source, target, width, height, horizontalAnchorPosition, verticalAnchorPosition, angle, borderColor, sourcePaddingElements, targetPaddingElements, 0u, 0u), 0u, height);
1955 rotate8BitPerChannelSubset<tChannels>(source, target, width, height, horizontalAnchorPosition, verticalAnchorPosition, angle, borderColor, sourcePaddingElements, targetPaddingElements, 0u, height);
1959 template <
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar>
1962 static_assert(tChannels != 0u,
"Invalid channel number!");
1963 static_assert(tPixelCenter ==
PC_TOP_LEFT || tPixelCenter ==
PC_CENTER,
"Invalid pixel center!");
1965 ocean_assert(frame !=
nullptr && result !=
nullptr);
1966 ocean_assert(width != 0u && height != 0u);
1968 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
1970 ocean_assert(position.
x() >= TScalar(0));
1971 ocean_assert(position.
y() >= TScalar(0));
1975 ocean_assert(position.
x() <= TScalar(width - 1u));
1976 ocean_assert(position.
y() <= TScalar(height - 1u));
1978 const unsigned int left = (
unsigned int)(position.
x());
1979 const unsigned int top = (
unsigned int)(position.
y());
1980 ocean_assert(left < width && top < height);
1982 const TScalar tx = position.
x() - TScalar(left);
1983 ocean_assert(tx >= 0 && tx <= 1);
1984 const unsigned int txi = (
unsigned int)(tx * TScalar(128) + TScalar(0.5));
1985 const unsigned int txi_ = 128u - txi;
1987 const TScalar ty = position.
y() - TScalar(top);
1988 ocean_assert(ty >= 0 && ty <= 1);
1989 const unsigned int tyi = (
unsigned int)(ty * TScalar(128) + TScalar(0.5));
1990 const unsigned int tyi_ = 128u - tyi;
1992 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
1993 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
1995 const uint8_t*
const topLeft = frame + top * frameStrideElements + tChannels * left;
1997 const unsigned int txty = txi * tyi;
1998 const unsigned int txty_ = txi * tyi_;
1999 const unsigned int tx_ty = txi_ * tyi;
2000 const unsigned int tx_ty_ = txi_ * tyi_;
2002 for (
unsigned int n = 0u; n < tChannels; ++n)
2004 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u);
2009 ocean_assert(tPixelCenter ==
PC_CENTER);
2011 ocean_assert(position.
x() <= TScalar(width));
2012 ocean_assert(position.
y() <= TScalar(height));
2014 const TScalar xShifted = std::max(TScalar(0.0), position.
x() - TScalar(0.5));
2015 const TScalar yShifted = std::max(TScalar(0.0), position.
y() - TScalar(0.5));
2017 const unsigned int left = (
unsigned int)(xShifted);
2018 const unsigned int top = (
unsigned int)(yShifted);
2020 ocean_assert(left < width);
2021 ocean_assert(top < height);
2023 const TScalar tx = xShifted - TScalar(left);
2024 const TScalar ty = yShifted - TScalar(top);
2026 ocean_assert(tx >= 0 && tx <= 1);
2027 ocean_assert(ty >= 0 && ty <= 1);
2029 const unsigned int txi = (
unsigned int)(tx * TScalar(128) + TScalar(0.5));
2030 const unsigned int txi_ = 128u - txi;
2032 const unsigned int tyi = (
unsigned int)(ty * TScalar(128) + TScalar(0.5));
2033 const unsigned int tyi_ = 128u - tyi;
2035 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2036 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2038 const uint8_t*
const topLeft = frame + top * frameStrideElements + left * tChannels;
2040 const unsigned int txty = txi * tyi;
2041 const unsigned int txty_ = txi * tyi_;
2042 const unsigned int tx_ty = txi_ * tyi;
2043 const unsigned int tx_ty_ = txi_ * tyi_;
2045 for (
unsigned int n = 0u; n < tChannels; ++n)
2047 result[n] = uint8_t((topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_ + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u);
2052 template <
typename TSource,
typename TTarget,
unsigned int tChannels, PixelCenter tPixelCenter,
typename TScalar,
typename TIntermediate>
2055 static_assert(tChannels != 0u,
"Invalid channel number!");
2056 static_assert(tPixelCenter ==
PC_TOP_LEFT || tPixelCenter ==
PC_CENTER,
"Invalid pixel center!");
2058 ocean_assert(frame !=
nullptr && result !=
nullptr);
2059 ocean_assert(width != 0u && height != 0u);
2061 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2063 ocean_assert(position.
x() >= TScalar(0));
2064 ocean_assert(position.
y() >= TScalar(0));
2068 ocean_assert(position.
x() <= TScalar(width - 1u));
2069 ocean_assert(position.
y() <= TScalar(height - 1u));
2071 const unsigned int left = (
unsigned int)(position.
x());
2072 const unsigned int top = (
unsigned int)(position.
y());
2074 const TScalar tx = position.
x() - TScalar(left);
2075 ocean_assert(tx >= 0 && tx <= 1);
2077 const TScalar ty = position.
y() - TScalar(top);
2078 ocean_assert(ty >= 0 && ty <= 1);
2080 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2081 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2083 const TSource*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2085 const TIntermediate txty = TIntermediate(tx) * TIntermediate(ty);
2086 const TIntermediate txty_ = TIntermediate(tx) * (TIntermediate(1) - TIntermediate(ty));
2087 const TIntermediate tx_ty = (TIntermediate(1) - TIntermediate(tx)) * TIntermediate(ty);
2088 const TIntermediate tx_ty_ = (TIntermediate(1) - TIntermediate(tx)) * (TIntermediate(1) - TIntermediate(ty));
2092 for (
unsigned int n = 0u; n < tChannels; ++n)
2094 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);
2099 ocean_assert(tPixelCenter ==
PC_CENTER);
2101 ocean_assert(position.
x() <= TScalar(width));
2102 ocean_assert(position.
y() <= TScalar(height));
2104 const TScalar xShifted = std::max(TScalar(0.0), position.
x() - TScalar(0.5));
2105 const TScalar yShifted = std::max(TScalar(0.0), position.
y() - TScalar(0.5));
2107 const unsigned int left = (
unsigned int)(xShifted);
2108 const unsigned int top = (
unsigned int)(yShifted);
2110 ocean_assert(left < width);
2111 ocean_assert(top < height);
2113 const TScalar tx = xShifted - TScalar(left);
2114 const TScalar ty = yShifted - TScalar(top);
2116 ocean_assert(tx >= 0 && tx <= 1);
2117 ocean_assert(ty >= 0 && ty <= 1);
2119 const unsigned int rightOffset = left + 1u < width ? tChannels : 0u;
2120 const unsigned int bottomOffset = top + 1u < height ? frameStrideElements : 0u;
2122 const TSource*
const topLeft = frame + top * frameStrideElements + tChannels * left;
2124 const TIntermediate txty = TIntermediate(tx) * TIntermediate(ty);
2125 const TIntermediate txty_ = TIntermediate(tx) * (TIntermediate(1) - TIntermediate(ty));
2126 const TIntermediate tx_ty = (TIntermediate(1) - TIntermediate(tx)) * TIntermediate(ty);
2127 const TIntermediate tx_ty_ = (TIntermediate(1) - TIntermediate(tx)) * (TIntermediate(1) - TIntermediate(ty));
2131 for (
unsigned int n = 0u; n < tChannels; ++n)
2133 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);
2138 template <
unsigned int tChannels,
bool tAlphaAtFront,
bool tTransparentIs0xFF>
2141 static_assert(tChannels != 0u,
"Invalid channel number!");
2143 ocean_assert(frame && result);
2150 for (
unsigned int n = 0u; n < tChannels - 1u; ++n)
2160 const unsigned int frameStrideElements = width * tChannels + framePaddingElements;
2165 ocean_assert(left >= -1 && left <
int(width));
2166 ocean_assert(top >= -1 && top <
int(height));
2168 if ((
unsigned int)left < width - 1u && (
unsigned int)top < height - 1u)
2172 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
2173 const unsigned int txi_ = 128u - txi;
2175 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
2176 const unsigned int tyi_ = 128u - tyi;
2178 const uint8_t*
const topLeft = frame + top * frameStrideElements + left * tChannels;
2180 const unsigned int txty = txi * tyi;
2181 const unsigned int txty_ = txi * tyi_;
2182 const unsigned int tx_ty = txi_ * tyi;
2183 const unsigned int tx_ty_ = txi_ * tyi_;
2185 for (
unsigned int n = 0u; n < tChannels; ++n)
2187 result[n] = (topLeft[n] * tx_ty_ + topLeft[tChannels + n] * txty_
2188 + topLeft[frameStrideElements + n] * tx_ty + topLeft[frameStrideElements + tChannels + n] * txty + 8192u) >> 14u;
2195 const unsigned int txi = (
unsigned int)((pos.
x() -
Scalar(left)) *
Scalar(128) +
Scalar(0.5));
2196 const unsigned int txi_ = 128u - txi;
2198 const unsigned int tyi = (
unsigned int)((pos.
y() -
Scalar(top)) *
Scalar(128) +
Scalar(0.5));
2199 const unsigned int tyi_ = 128u - tyi;
2201 const unsigned int rightOffset = (left >= 0 && left + 1u < width) ? tChannels : 0u;
2202 const unsigned int bottomOffset = (top >= 0 && top + 1u < height) ? frameStrideElements : 0u;
2204 ocean_assert(left <
int(width) && top <
int(height));
2205 const uint8_t*
const topLeft = frame + max(0, top) * frameStrideElements + max(0, left) * tChannels;
2207 const unsigned int txty = txi * tyi;
2208 const unsigned int txty_ = txi * tyi_;
2209 const unsigned int tx_ty = txi_ * tyi;
2210 const unsigned int tx_ty_ = txi_ * tyi_;
2214 result[n] = (topLeft[n] * tx_ty_ + topLeft[rightOffset + n] * txty_
2215 + topLeft[bottomOffset + n] * tx_ty + topLeft[bottomOffset + rightOffset + n] * txty + 8192u) >> 14u;
2227 template <
unsigned int tChannels>
2228 void 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)
2230 static_assert(tChannels >= 1u,
"Invalid channel number!");
2232 ocean_assert(source !=
nullptr && target !=
nullptr);
2233 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
2234 ocean_assert_and_suppress_unused(targetWidth > 0u && targetHeight > 0u, targetHeight);
2235 ocean_assert(source_A_target);
2238 ocean_assert(firstTargetRow + numberOutputRows <= targetHeight);
2240 const unsigned int targetStrideElements = tChannels * targetWidth + targetPaddingElements;
2242 const Scalar scalarSourceWidth_1 =
Scalar(sourceWidth - 1u);
2243 const Scalar scalarSourceHeight_1 =
Scalar(sourceHeight - 1u);
2247 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2248 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2250 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberOutputRows; ++y)
2252 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
2278 for (
unsigned int x = 0u; x < targetWidth; ++x)
2283 const Scalar debugSourceX = (*source_A_target)[0] *
Scalar(x) + (*source_A_target)[3] *
Scalar(y) + (*source_A_target)[6];
2284 const Scalar debugSourceY = (*source_A_target)[1] *
Scalar(x) + (*source_A_target)[4] *
Scalar(y) + (*source_A_target)[7];
2288 if (sourcePosition.
x() <
Scalar(0) || sourcePosition.
x() > scalarSourceWidth_1 || sourcePosition.
y() <
Scalar(0) || sourcePosition.
y() > scalarSourceHeight_1)
2290 *targetRow = *bColor;
2294 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(source, sourceWidth, sourceHeight, sourcePaddingElements, sourcePosition, (uint8_t*)(targetRow));
2302 template <
unsigned int tChannels>
2303 void 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)
2305 static_assert(tChannels >= 1u,
"Invalid channel number!");
2307 ocean_assert(input !=
nullptr && output !=
nullptr);
2308 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2309 ocean_assert(outputWidth > 0u && outputHeight > 0u);
2310 ocean_assert(input_H_output !=
nullptr);
2312 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
2314 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2316 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
2317 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
2321 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2322 const PixelType bColor = borderColor ? *(PixelType*)borderColor : *(PixelType*)zeroColor;
2324 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2350 const Scalar X2 = (*input_H_output)(2, 0);
2351 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
2353 PixelType* outputRowPixel = (PixelType*)(output + y * outputStrideElements);
2355 for (
unsigned int x = 0u; x < outputWidth; ++x)
2362 ocean_assert(inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
2365 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
2367 *outputRowPixel = bColor;
2371 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputRowPixel));
2379 template <
typename T,
unsigned int tChannels>
2380 void 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)
2382 static_assert(tChannels >= 1u,
"Invalid channel number!");
2384 ocean_assert(input !=
nullptr && output !=
nullptr);
2385 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2386 ocean_assert_and_suppress_unused(outputWidth > 0u && outputHeight > 0u, outputHeight);
2387 ocean_assert(input_H_output !=
nullptr);
2389 ocean_assert(firstOutputRow + numberOutputRows <= outputHeight);
2391 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2393 const Scalar scalarInputWidth1 =
Scalar(inputWidth - 1u);
2394 const Scalar scalarInputHeight1 =
Scalar(inputHeight - 1u);
2401 constexpr T zeroColor[tChannels] = {T(0)};
2402 const PixelType*
const bColor = borderColor ? (PixelType*)(borderColor) : (PixelType*)(zeroColor);
2404 constexpr TIntermediate bias = TIntermediate(0);
2406 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2432 const Scalar X2 = (*input_H_output)(2, 0);
2433 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
2435 PixelType* outputRowPixel = (PixelType*)(output + y * outputStrideElements);
2437 for (
unsigned int x = 0u; x < outputWidth; ++x)
2444 ocean_assert((std::is_same<float, Scalar>::value) || inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
2447 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
x() <= scalarInputWidth1 && inputPosition.
y() >=
Scalar(0) && inputPosition.
y() <= scalarInputHeight1)
2449 interpolatePixel<T, T, tChannels, CV::PC_TOP_LEFT, Scalar, TIntermediate>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (T*)(outputRowPixel), bias);
2453 *outputRowPixel = *bColor;
2461 #if defined(OCEAN_HARDWARE_SSE_VERSION) && OCEAN_HARDWARE_SSE_VERSION >= 41
2463 template <
unsigned int tChannels>
2464 inline 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)
2466 static_assert(tChannels >= 1u,
"Invalid channel number!");
2468 ocean_assert(source && target);
2469 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
2470 ocean_assert(targetWidth >= 4u && targetHeight > 0u);
2471 ocean_assert(source_A_target);
2474 ocean_assert_and_suppress_unused(firstTargetRow + numberTargetRows <= targetHeight, targetHeight);
2476 const unsigned int sourceStrideElements = tChannels * sourceWidth + sourcePaddingElements;
2477 const unsigned int targetStrideElements = tChannels * targetWidth + targetPaddingElements;
2481 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2482 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2484 OCEAN_ALIGN_DATA(16)
unsigned int validPixels[4];
2486 OCEAN_ALIGN_DATA(16)
unsigned int topLeftOffsets[4];
2487 OCEAN_ALIGN_DATA(16)
unsigned int topRightOffsets[4];
2488 OCEAN_ALIGN_DATA(16)
unsigned int bottomLeftOffsets[4];
2489 OCEAN_ALIGN_DATA(16)
unsigned int bottomRightOffsets[4];
2492 const __m128 m128_f_X0 = _mm_set_ps1(
float((*source_A_target)(0, 0)));
2493 const __m128 m128_f_X1 = _mm_set_ps1(
float((*source_A_target)(1, 0)));
2495 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
2497 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
2521 const __m128 m128_f_C0 = _mm_set_ps1(
float((*source_A_target)(0, 1) *
Scalar(y) + (*source_A_target)(0, 2)));
2522 const __m128 m128_f_C1 = _mm_set_ps1(
float((*source_A_target)(1, 1) *
Scalar(y) + (*source_A_target)(1, 2)));
2525 const __m128 m128_f_zero = _mm_setzero_ps();
2528 const __m128i m128_i_channels = _mm_set1_epi32(tChannels);
2531 const __m128i m128_i_sourceStrideElements = _mm_set1_epi32(sourceStrideElements);
2534 const __m128i m128_i_sourceWidth_1 = _mm_set1_epi32(
int(sourceWidth) - 1);
2535 const __m128i m128_i_sourceHeight_1 = _mm_set1_epi32(
int(sourceHeight) - 1);
2538 const __m128 m128_f_sourceWidth_1 = _mm_set_ps1(
float(sourceWidth - 1u));
2539 const __m128 m128_f_sourceHeight_1 = _mm_set_ps1(
float(sourceHeight - 1u));
2541 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
2543 if (x + 4u > targetWidth)
2548 ocean_assert(x >= 4u && targetWidth > 4u);
2549 const unsigned int newX = targetWidth - 4u;
2551 ocean_assert(x > newX);
2552 targetRow -= x - newX;
2557 ocean_assert(!(x + 4u < targetWidth));
2563 const __m128 m128_f_x_0123 = _mm_set_ps(
float(x + 3u),
float(x + 2u),
float(x + 1u),
float(x + 0u));
2566 const __m128 m128_f_sourceX = _mm_add_ps(_mm_mul_ps(m128_f_X0, m128_f_x_0123), m128_f_C0);
2567 const __m128 m128_f_sourceY = _mm_add_ps(_mm_mul_ps(m128_f_X1, m128_f_x_0123), m128_f_C1);
2570 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));
2571 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));
2573 const __m128i m128_i_validPixel = _mm_castps_si128(_mm_and_ps(m128_f_validPixelX, m128_f_validPixelY));
2576 if (_mm_test_all_zeros(m128_i_validPixel, _mm_set1_epi32(0xFFFFFFFF)))
2579 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
2580 _mm_store_si128((__m128i*)debugValidPixels, m128_i_validPixel);
2581 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
2584 targetRow[0] = *bColor;
2585 targetRow[1] = *bColor;
2586 targetRow[2] = *bColor;
2587 targetRow[3] = *bColor;
2595 _mm_store_si128((__m128i*)validPixels, m128_i_validPixel);
2596 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
2600 const __m128 m128_f_tx_floor = _mm_floor_ps(m128_f_sourceX);
2601 const __m128 m128_f_ty_floor = _mm_floor_ps(m128_f_sourceY);
2604 const __m128i m128_i_left = _mm_cvtps_epi32(m128_f_tx_floor);
2605 const __m128i m128_i_top = _mm_cvtps_epi32(m128_f_ty_floor);
2608 const __m128i m128_i_right = _mm_min_epu32(_mm_add_epi32(m128_i_left, _mm_set1_epi32(1)), m128_i_sourceWidth_1);
2609 const __m128i m128_i_bottom = _mm_min_epu32(_mm_add_epi32(m128_i_top, _mm_set1_epi32(1)), m128_i_sourceHeight_1);
2612 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));
2613 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));
2614 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));
2615 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));
2618 _mm_store_si128((__m128i*)topLeftOffsets, m128_i_topLeftOffset);
2619 _mm_store_si128((__m128i*)topRightOffsets, m128_i_topRightOffset);
2620 _mm_store_si128((__m128i*)bottomLeftOffsets, m128_i_bottomLeftOffset);
2621 _mm_store_si128((__m128i*)bottomRightOffsets, m128_i_bottomRightOffset);
2629 __m128 m128_f_tx = _mm_sub_ps(m128_f_sourceX, m128_f_tx_floor);
2630 __m128 m128_f_ty = _mm_sub_ps(m128_f_sourceY, m128_f_ty_floor);
2633 m128_f_tx = _mm_mul_ps(m128_f_tx, _mm_set_ps1(128.0f));
2634 m128_f_ty = _mm_mul_ps(m128_f_ty, _mm_set_ps1(128.0f));
2636 m128_f_tx = _mm_round_ps(m128_f_tx, _MM_FROUND_TO_NEAREST_INT);
2637 m128_f_ty = _mm_round_ps(m128_f_ty, _MM_FROUND_TO_NEAREST_INT);
2639 const __m128i m128_i_tx = _mm_cvtps_epi32(m128_f_tx);
2640 const __m128i m128_i_ty = _mm_cvtps_epi32(m128_f_ty);
2642 interpolate4Pixels8BitPerChannelSSE<tChannels>(source, topLeftOffsets, topRightOffsets, bottomLeftOffsets, bottomRightOffsets, validPixels, *bColor, m128_i_tx, m128_i_ty, targetRow);
2648 template <
unsigned int tChannels>
2649 inline 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)
2651 static_assert(tChannels >= 1u,
"Invalid channel number!");
2653 ocean_assert(input !=
nullptr && output !=
nullptr);
2654 ocean_assert(inputWidth > 0u && inputHeight > 0u);
2655 ocean_assert(outputWidth >= 4u && outputHeight > 0u);
2656 ocean_assert(input_H_output !=
nullptr);
2658 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
2660 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
2661 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
2665 uint8_t zeroColor[tChannels] = {uint8_t(0)};
2666 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
2668 OCEAN_ALIGN_DATA(16)
unsigned int validPixels[4];
2670 OCEAN_ALIGN_DATA(16)
unsigned int topLeftOffsets[4];
2671 OCEAN_ALIGN_DATA(16)
unsigned int topRightOffsets[4];
2672 OCEAN_ALIGN_DATA(16)
unsigned int bottomLeftOffsets[4];
2673 OCEAN_ALIGN_DATA(16)
unsigned int bottomRightOffsets[4];
2676 const __m128 m128_f_X0 = _mm_set_ps1(
float((*input_H_output)(0, 0)));
2677 const __m128 m128_f_X1 = _mm_set_ps1(
float((*input_H_output)(1, 0)));
2678 const __m128 m128_f_X2 = _mm_set_ps1(
float((*input_H_output)(2, 0)));
2681 const __m128 m128_f_zero = _mm_setzero_ps();
2684 const __m128i m128_i_channels = _mm_set1_epi32(tChannels);
2687 const __m128i m128_i_inputStrideElements = _mm_set1_epi32(inputStrideElements);
2690 const __m128i m128_i_inputWidth_1 = _mm_set1_epi32(
int(inputWidth) - 1);
2691 const __m128i m128_i_inputHeight_1 = _mm_set1_epi32(
int(inputHeight) - 1);
2694 const __m128 m128_f_inputWidth_1 = _mm_set_ps1(
float(inputWidth - 1u));
2695 const __m128 m128_f_inputHeight_1 = _mm_set_ps1(
float(inputHeight - 1u));
2697 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
2699 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
2723 const __m128 m128_f_C0 = _mm_set_ps1(
float((*input_H_output)(0, 1) *
Scalar(y) + (*input_H_output)(0, 2)));
2724 const __m128 m128_f_C1 = _mm_set_ps1(
float((*input_H_output)(1, 1) *
Scalar(y) + (*input_H_output)(1, 2)));
2725 const __m128 m128_f_C2 = _mm_set_ps1(
float((*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2)));
2727 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
2729 if (x + 4u > outputWidth)
2734 ocean_assert(x >= 4u && outputWidth > 4u);
2735 const unsigned int newX = outputWidth - 4u;
2737 ocean_assert(x > newX);
2738 outputPixelData -= x - newX;
2743 ocean_assert(!(x + 4u < outputWidth));
2749 const __m128 m128_f_x_0123 = _mm_set_ps(
float(x + 3u),
float(x + 2u),
float(x + 1u),
float(x + 0u));
2752 const __m128 m128_f_xx = _mm_add_ps(_mm_mul_ps(m128_f_X0, m128_f_x_0123), m128_f_C0);
2753 const __m128 m128_f_yy = _mm_add_ps(_mm_mul_ps(m128_f_X1, m128_f_x_0123), m128_f_C1);
2754 const __m128 m128_f_zz = _mm_add_ps(_mm_mul_ps(m128_f_X2, m128_f_x_0123), m128_f_C2);
2756 #ifdef USE_APPROXIMATED_INVERSE_OF_ZZ
2761 const __m128 inv_zz_128 = _mm_rcp_ps(m128_f_zz);
2764 const __m128 m128_f_inputX = _mm_mul_ps(m128_f_xx, inv_zz_128);
2765 const __m128 m128_f_inputY = _mm_mul_ps(m128_f_yy, inv_zz_128);
2770 const __m128 m128_f_inputX = _mm_div_ps(m128_f_xx, m128_f_zz);
2771 const __m128 m128_f_inputY = _mm_div_ps(m128_f_yy, m128_f_zz);
2777 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));
2778 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));
2780 const __m128i m128_i_validPixel = _mm_castps_si128(_mm_and_ps(m128_f_validPixelX, m128_f_validPixelY));
2783 if (_mm_test_all_zeros(m128_i_validPixel, _mm_set1_epi32(0xFFFFFFFF)))
2786 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
2787 _mm_store_si128((__m128i*)debugValidPixels, m128_i_validPixel);
2788 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
2791 outputPixelData[0] = *bColor;
2792 outputPixelData[1] = *bColor;
2793 outputPixelData[2] = *bColor;
2794 outputPixelData[3] = *bColor;
2796 outputPixelData += 4;
2802 _mm_store_si128((__m128i*)validPixels, m128_i_validPixel);
2803 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
2807 const __m128 m128_f_tx_floor = _mm_floor_ps(m128_f_inputX);
2808 const __m128 m128_f_ty_floor = _mm_floor_ps(m128_f_inputY);
2811 const __m128i m128_i_left = _mm_cvtps_epi32(m128_f_tx_floor);
2812 const __m128i m128_i_top = _mm_cvtps_epi32(m128_f_ty_floor);
2815 const __m128i m128_i_right = _mm_min_epu32(_mm_add_epi32(m128_i_left, _mm_set1_epi32(1)), m128_i_inputWidth_1);
2816 const __m128i m128_i_bottom = _mm_min_epu32(_mm_add_epi32(m128_i_top, _mm_set1_epi32(1)), m128_i_inputHeight_1);
2819 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));
2820 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));
2821 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));
2822 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));
2825 _mm_store_si128((__m128i*)topLeftOffsets, m128_i_topLeftOffset);
2826 _mm_store_si128((__m128i*)topRightOffsets, m128_i_topRightOffset);
2827 _mm_store_si128((__m128i*)bottomLeftOffsets, m128_i_bottomLeftOffset);
2828 _mm_store_si128((__m128i*)bottomRightOffsets, m128_i_bottomRightOffset);
2836 __m128 m128_f_tx = _mm_sub_ps(m128_f_inputX, m128_f_tx_floor);
2837 __m128 m128_f_ty = _mm_sub_ps(m128_f_inputY, m128_f_ty_floor);
2840 m128_f_tx = _mm_mul_ps(m128_f_tx, _mm_set_ps1(128.0f));
2841 m128_f_ty = _mm_mul_ps(m128_f_ty, _mm_set_ps1(128.0f));
2843 m128_f_tx = _mm_round_ps(m128_f_tx, _MM_FROUND_TO_NEAREST_INT);
2844 m128_f_ty = _mm_round_ps(m128_f_ty, _MM_FROUND_TO_NEAREST_INT);
2846 const __m128i m128_i_tx = _mm_cvtps_epi32(m128_f_tx);
2847 const __m128i m128_i_ty = _mm_cvtps_epi32(m128_f_ty);
2849 interpolate4Pixels8BitPerChannelSSE<tChannels>(input, topLeftOffsets, topRightOffsets, bottomLeftOffsets, bottomRightOffsets, validPixels, *bColor, m128_i_tx, m128_i_ty, outputPixelData);
2850 outputPixelData += 4;
2856 OCEAN_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)
2873 const __m128i mask32_Channel0 =
SSE::set128i(0xFFFFFF09FFFFFF06ull, 0xFFFFFF03FFFFFF00ull);
2874 const __m128i mask32_Channel1 =
SSE::set128i(0xFFFFFF0AFFFFFF07ull, 0xFFFFFF04FFFFFF01ull);
2875 const __m128i mask32_Channel2 =
SSE::set128i(0xFFFFFF0BFFFFFF08ull, 0xFFFFFF05FFFFFF02ull);
2883 __m128i multiplication_channel0 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel0));
2886 __m128i multiplication_channel1 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel1));
2889 __m128i multiplication_channel2 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel2));
2893 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel0)));
2894 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel1)));
2895 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel2)));
2899 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel0)));
2900 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel1)));
2901 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel2)));
2905 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel0)));
2906 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel1)));
2907 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel2)));
2910 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
2919 __m128i interpolation_channel0 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel0, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFFFF0CFFull, 0xFF08FFFF04FFFF00ull));
2925 __m128i interpolation_channel1 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel1, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFF0CFFFFull, 0x08FFFF04FFFF00FFull));
2931 __m128i interpolation_channel2 = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication_channel2, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFF0CFFFF08ull, 0xFFFF04FFFF00FFFFull));
2936 return _mm_or_si128(_mm_or_si128(interpolation_channel0, interpolation_channel1), interpolation_channel2);
2940 OCEAN_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)
2957 const __m128i mask32_Channel0 =
SSE::set128i(0xA0A0A00CA0A0A008ull, 0xA0A0A004A0A0A000ull);
2958 const __m128i mask32_Channel1 =
SSE::set128i(0xA0A0A00DA0A0A009ull, 0xA0A0A005A0A0A001ull);
2959 const __m128i mask32_Channel2 =
SSE::set128i(0xA0A0A00EA0A0A00Aull, 0xA0A0A006A0A0A002ull);
2960 const __m128i mask32_Channel3 =
SSE::set128i(0xA0A0A00FA0A0A00Bull, 0xA0A0A007A0A0A003ull);
2968 __m128i multiplication_channel0 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel0));
2971 __m128i multiplication_channel1 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel1));
2974 __m128i multiplication_channel2 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel2));
2977 __m128i multiplication_channel3 = _mm_mullo_epi32(factorsTopLeft, _mm_shuffle_epi8(sourcesTopLeft, mask32_Channel3));
2981 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel0)));
2982 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel1)));
2983 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel2)));
2984 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsTopRight, _mm_shuffle_epi8(sourcesTopRight, mask32_Channel3)));
2988 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel0)));
2989 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel1)));
2990 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel2)));
2991 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsBottomLeft, _mm_shuffle_epi8(sourcesBottomLeft, mask32_Channel3)));
2995 multiplication_channel0 = _mm_add_epi32(multiplication_channel0, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel0)));
2996 multiplication_channel1 = _mm_add_epi32(multiplication_channel1, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel1)));
2997 multiplication_channel2 = _mm_add_epi32(multiplication_channel2, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel2)));
2998 multiplication_channel3 = _mm_add_epi32(multiplication_channel3, _mm_mullo_epi32(factorsBottomRight, _mm_shuffle_epi8(sourcesBottomRight, mask32_Channel3)));
3001 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
3008 __m128i interpolation_channel0 = _mm_srli_epi32(_mm_add_epi32(multiplication_channel0, m128_i_8192), 14);
3013 __m128i interpolation_channel1 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel1, m128_i_8192), 14), 8);
3017 __m128i interpolation_channel2 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel2, m128_i_8192), 14), 16);
3021 __m128i interpolation_channel3 = _mm_slli_epi32(_mm_srli_epi32(_mm_add_epi32(multiplication_channel3, m128_i_8192), 14), 24);
3026 return _mm_or_si128(_mm_or_si128(interpolation_channel0, interpolation_channel1), _mm_or_si128(interpolation_channel2, interpolation_channel3));
3029 #ifdef OCEAN_COMPILER_MSC
3035 OCEAN_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)
3037 ocean_assert(source !=
nullptr);
3038 ocean_assert(targetPositionPixels !=
nullptr);
3044 OCEAN_ALIGN_DATA(16) PixelType pixels[16];
3048 for (
unsigned int i = 0u; i < 4u; ++i)
3052 pixels[i * 4u + 0u] = *((PixelType*)(source + offsetsTopLeft[i]));
3053 pixels[i * 4u + 1u] = *((PixelType*)(source + offsetsTopRight[i]));
3054 pixels[i * 4u + 2u] = *((PixelType*)(source + offsetsBottomLeft[i]));
3055 pixels[i * 4u + 3u] = *((PixelType*)(source + offsetsBottomRight[i]));
3059 pixels[i * 4u + 0u] = borderColor;
3060 pixels[i * 4u + 1u] = borderColor;
3061 pixels[i * 4u + 2u] = borderColor;
3062 pixels[i * 4u + 3u] = borderColor;
3066 static_assert(
sizeof(__m128i) ==
sizeof(pixels),
"Invalid data type!");
3068 const __m128i m128_pixels = _mm_load_si128((
const __m128i*)pixels);
3074 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3075 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3080 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3081 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3082 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3083 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3099 const __m128i mask32_topLeft =
SSE::set128i(0xFFFFFF0CFFFFFF08ull, 0xFFFFFF04FFFFFF00ull);
3100 const __m128i mask32_topRight =
SSE::set128i(0xFFFFFF0DFFFFFF09ull, 0xFFFFFF05FFFFFF01ull);
3101 const __m128i mask32_bottomLeft =
SSE::set128i(0xFFFFFF0EFFFFFF0Aull, 0xFFFFFF06FFFFFF02ull);
3102 const __m128i mask32_bottomRight =
SSE::set128i(0xFFFFFF0FFFFFFF0Bull, 0xFFFFFF07FFFFFF03ull);
3110 __m128i multiplicationA = _mm_mullo_epi32(m128_factorsTopLeft, _mm_shuffle_epi8(m128_pixels, mask32_topLeft));
3111 __m128i multiplicationB = _mm_mullo_epi32(m128_factorsTopRight, _mm_shuffle_epi8(m128_pixels, mask32_topRight));
3113 multiplicationA = _mm_add_epi32(multiplicationA, _mm_mullo_epi32(m128_factorsBottomLeft, _mm_shuffle_epi8(m128_pixels, mask32_bottomLeft)));
3114 multiplicationB = _mm_add_epi32(multiplicationB, _mm_mullo_epi32(m128_factorsBottomRight, _mm_shuffle_epi8(m128_pixels, mask32_bottomRight)));
3116 __m128i multiplication = _mm_add_epi32(multiplicationA, multiplicationB);
3118 const __m128i m128_i_8192 = _mm_set1_epi32(8192);
3123 const __m128i result = _mm_shuffle_epi8(_mm_srli_epi32(_mm_add_epi32(multiplication, m128_i_8192), 14),
SSE::set128i(0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF0C080400ull));
3125 *((
unsigned int*)targetPositionPixels) = _mm_extract_epi32(result, 0);
3129 OCEAN_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)
3131 ocean_assert(source !=
nullptr);
3132 ocean_assert(targetPositionPixels !=
nullptr);
3138 OCEAN_ALIGN_DATA(16) PixelType topLeftPixels[6];
3139 OCEAN_ALIGN_DATA(16) PixelType topRightPixels[6];
3140 OCEAN_ALIGN_DATA(16) PixelType bottomLeftPixels[6];
3141 OCEAN_ALIGN_DATA(16) PixelType bottomRightPixels[6];
3145 for (
unsigned int i = 0u; i < 4u; ++i)
3149 topLeftPixels[i] = *((PixelType*)(source + offsetsTopLeft[i]));
3150 topRightPixels[i] = *((PixelType*)(source + offsetsTopRight[i]));
3151 bottomLeftPixels[i] = *((PixelType*)(source + offsetsBottomLeft[i]));
3152 bottomRightPixels[i] = *((PixelType*)(source + offsetsBottomRight[i]));
3156 topLeftPixels[i] = borderColor;
3157 topRightPixels[i] = borderColor;
3158 bottomLeftPixels[i] = borderColor;
3159 bottomRightPixels[i] = borderColor;
3163 static_assert(
sizeof(__m128i) <=
sizeof(topLeftPixels),
"Invalid data type!");
3165 const __m128i m128_topLeftPixels = _mm_load_si128((
const __m128i*)topLeftPixels);
3166 const __m128i m128_topRightPixels = _mm_load_si128((
const __m128i*)topRightPixels);
3167 const __m128i m128_bottomLeftPixels = _mm_load_si128((
const __m128i*)bottomLeftPixels);
3168 const __m128i m128_bottomRightPixels = _mm_load_si128((
const __m128i*)bottomRightPixels);
3174 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3175 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3180 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3181 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3182 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3183 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3186 const __m128i m128_interpolationResult = interpolate4Pixels8BitPerChannelSSE<3u>(m128_topLeftPixels, m128_topRightPixels, m128_bottomLeftPixels, m128_bottomRightPixels, m128_factorsTopLeft, m128_factorsTopRight, m128_factorsBottomLeft, m128_factorsBottomRight);
3189 memcpy(targetPositionPixels, &m128_interpolationResult, 12u);
3195 OCEAN_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)
3197 ocean_assert(source !=
nullptr);
3198 ocean_assert(targetPositionPixels !=
nullptr);
3204 OCEAN_ALIGN_DATA(16) PixelType topLeftPixels[4];
3205 OCEAN_ALIGN_DATA(16) PixelType topRightPixels[4];
3206 OCEAN_ALIGN_DATA(16) PixelType bottomLeftPixels[4];
3207 OCEAN_ALIGN_DATA(16) PixelType bottomRightPixels[4];
3212 for (
unsigned int i = 0u; i < 4u; ++i)
3216 topLeftPixels[i] = *((PixelType*)(source + offsetsTopLeft[i]));
3217 topRightPixels[i] = *((PixelType*)(source + offsetsTopRight[i]));
3218 bottomLeftPixels[i] = *((PixelType*)(source + offsetsBottomLeft[i]));
3219 bottomRightPixels[i] = *((PixelType*)(source + offsetsBottomRight[i]));
3223 topLeftPixels[i] = borderColor;
3224 topRightPixels[i] = borderColor;
3225 bottomLeftPixels[i] = borderColor;
3226 bottomRightPixels[i] = borderColor;
3230 static_assert(
sizeof(__m128i) ==
sizeof(topLeftPixels),
"Invalid data type!");
3232 const __m128i m128_topLeftPixels = _mm_load_si128((
const __m128i*)topLeftPixels);
3233 const __m128i m128_topRightPixels = _mm_load_si128((
const __m128i*)topRightPixels);
3234 const __m128i m128_bottomLeftPixels = _mm_load_si128((
const __m128i*)bottomLeftPixels);
3235 const __m128i m128_bottomRightPixels = _mm_load_si128((
const __m128i*)bottomRightPixels);
3241 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3242 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3247 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3248 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3249 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3250 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3253 const __m128i m128_interpolationResult = interpolate4Pixels8BitPerChannelSSE<4u>(m128_topLeftPixels, m128_topRightPixels, m128_bottomLeftPixels, m128_bottomRightPixels, m128_factorsTopLeft, m128_factorsTopRight, m128_factorsBottomLeft, m128_factorsBottomRight);
3255 _mm_storeu_si128((__m128i*)targetPositionPixels, m128_interpolationResult);
3258 template <
unsigned int tChannels>
3259 OCEAN_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)
3261 ocean_assert(source !=
nullptr);
3262 ocean_assert(targetPositionPixels !=
nullptr);
3266 OCEAN_ALIGN_DATA(16)
unsigned int factorsTopLeft[4];
3267 OCEAN_ALIGN_DATA(16)
unsigned int factorsTopRight[4];
3268 OCEAN_ALIGN_DATA(16)
unsigned int factorsBottomLeft[4];
3269 OCEAN_ALIGN_DATA(16)
unsigned int factorsBottomRight[4];
3275 const __m128i m128_factorsLeft = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsRight);
3276 const __m128i m128_factorsTop = _mm_sub_epi32(_mm_set1_epi32(128), m128_factorsBottom);
3281 const __m128i m128_factorsTopLeft = _mm_mullo_epi32(m128_factorsTop, m128_factorsLeft);
3282 const __m128i m128_factorsTopRight = _mm_mullo_epi32(m128_factorsTop, m128_factorsRight);
3283 const __m128i m128_factorsBottomLeft = _mm_mullo_epi32(m128_factorsBottom, m128_factorsLeft);
3284 const __m128i m128_factorsBottomRight = _mm_mullo_epi32(m128_factorsBottom, m128_factorsRight);
3288 _mm_store_si128((__m128i*)factorsTopLeft, m128_factorsTopLeft);
3289 _mm_store_si128((__m128i*)factorsTopRight, m128_factorsTopRight);
3290 _mm_store_si128((__m128i*)factorsBottomLeft, m128_factorsBottomLeft);
3291 _mm_store_si128((__m128i*)factorsBottomRight, m128_factorsBottomRight);
3293 for (
unsigned int i = 0u; i < 4u; ++i)
3297 const uint8_t* topLeft = source + offsetsTopLeft[i];
3298 const uint8_t* topRight = source + offsetsTopRight[i];
3300 const uint8_t* bottomLeft = source + offsetsBottomLeft[i];
3301 const uint8_t* bottomRight = source + offsetsBottomRight[i];
3303 const unsigned int& factorTopLeft = factorsTopLeft[i];
3304 const unsigned int& factorTopRight = factorsTopRight[i];
3305 const unsigned int& factorBottomLeft = factorsBottomLeft[i];
3306 const unsigned int& factorBottomRight = factorsBottomRight[i];
3308 for (
unsigned int n = 0u; n < tChannels; ++n)
3310 ((uint8_t*)targetPositionPixels)[n] = (uint8_t)((topLeft[n] * factorTopLeft + topRight[n] * factorTopRight + bottomLeft[n] * factorBottomLeft + bottomRight[n] * factorBottomRight + 8192u) >> 14u);
3315 *targetPositionPixels = borderColor;
3318 targetPositionPixels++;
3324 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
3326 template <
unsigned int tChannels>
3327 void 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)
3329 static_assert(tChannels >= 1u,
"Invalid channel number!");
3331 ocean_assert(source && target);
3332 ocean_assert(sourceWidth > 0u && sourceHeight > 0u);
3333 ocean_assert(targetWidth >= 4u && targetHeight > 0u);
3334 ocean_assert(source_A_target);
3337 ocean_assert(firstTargetRow + numberTargetRows <= targetHeight);
3339 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
3340 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
3344 uint8_t zeroColor[tChannels] = {uint8_t(0)};
3345 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
3347 unsigned int validPixels[4];
3349 unsigned int topLeftOffsetsElements[4];
3350 unsigned int topRightOffsetsElements[4];
3351 unsigned int bottomLeftOffsetsElements[4];
3352 unsigned int bottomRightOffsetsElements[4];
3354 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
3357 const float32x4_t m128_f_X0 = vdupq_n_f32(
float((*source_A_target)(0, 0)));
3358 const float32x4_t m128_f_X1 = vdupq_n_f32(
float((*source_A_target)(1, 0)));
3360 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
3362 PixelType* targetRow = (PixelType*)(target + y * targetStrideElements);
3386 const float32x4_t m128_f_C0 = vdupq_n_f32(
float((*source_A_target)(0, 1) *
Scalar(y) + (*source_A_target)(0, 2)));
3387 const float32x4_t m128_f_C1 = vdupq_n_f32(
float((*source_A_target)(1, 1) *
Scalar(y) + (*source_A_target)(1, 2)));
3390 const float32x4_t m128_f_zero = vdupq_n_f32(0.0f);
3393 const uint32x4_t m128_u_sourceStrideElements = vdupq_n_u32(sourceStrideElements);
3396 const uint32x4_t m128_u_sourceWidth_1 = vdupq_n_u32(sourceWidth - 1u);
3397 const uint32x4_t m128_u_sourceHeight_1 = vdupq_n_u32(sourceHeight - 1u);
3400 const float32x4_t m128_f_sourceWidth_1 = vdupq_n_f32(
float(sourceWidth - 1u));
3401 const float32x4_t m128_f_sourceHeight_1 = vdupq_n_f32(
float(sourceHeight - 1u));
3403 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
3405 if (x + 4u > targetWidth)
3410 ocean_assert(x >= 4u && targetWidth > 4u);
3411 const unsigned int newX = targetWidth - 4u;
3413 ocean_assert(x > newX);
3414 targetRow -= x - newX;
3419 ocean_assert(!(x + 4u < targetWidth));
3425 float x_0123[4] = {float(x + 0u), float(x + 1u), float(x + 2u), float(x + 3u)};
3426 const float32x4_t m128_f_x_0123 = vld1q_f32(x_0123);
3429 const float32x4_t m128_f_sourceX = vmlaq_f32(m128_f_C0, m128_f_X0, m128_f_x_0123);
3430 const float32x4_t m128_f_sourceY = vmlaq_f32(m128_f_C1, m128_f_X1, m128_f_x_0123);
3434 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));
3435 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));
3437 const uint32x4_t m128_u_validPixel = vandq_u32(m128_u_validPixelX, m128_u_validPixelY);
3441 const uint32x2_t m64_u_validPixel = vorr_u32(vget_low_u32(m128_u_validPixel), vget_high_u32(m128_u_validPixel));
3442 if ((vget_lane_u32(m64_u_validPixel, 0) | vget_lane_u32(m64_u_validPixel, 1)) == 0x00000000u)
3445 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
3446 vst1q_u32(debugValidPixels, m128_u_validPixel);
3447 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
3450 targetRow[0] = *bColor;
3451 targetRow[1] = *bColor;
3452 targetRow[2] = *bColor;
3453 targetRow[3] = *bColor;
3462 vst1q_u32(validPixels, m128_u_validPixel);
3463 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
3468 const uint32x4_t m128_u_left = vcvtq_u32_f32(m128_f_sourceX);
3469 const uint32x4_t m128_u_top = vcvtq_u32_f32(m128_f_sourceY);
3472 const uint32x4_t m128_u_right = vminq_u32(vaddq_u32(m128_u_left, vdupq_n_u32(1u)), m128_u_sourceWidth_1);
3473 const uint32x4_t m128_u_bottom = vminq_u32(vaddq_u32(m128_u_top, vdupq_n_u32(1u)), m128_u_sourceHeight_1);
3476 const uint32x4_t m128_u_topLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_top, m128_u_sourceStrideElements);
3477 const uint32x4_t m128_u_topRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_top, m128_u_sourceStrideElements);
3478 const uint32x4_t m128_u_bottomLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_bottom, m128_u_sourceStrideElements);
3479 const uint32x4_t m128_u_bottomRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_bottom, m128_u_sourceStrideElements);
3482 vst1q_u32(topLeftOffsetsElements, m128_u_topLeftOffsetElements);
3483 vst1q_u32(topRightOffsetsElements, m128_u_topRightOffsetElements);
3484 vst1q_u32(bottomLeftOffsetsElements, m128_u_bottomLeftOffsetElements);
3485 vst1q_u32(bottomRightOffsetsElements, m128_u_bottomRightOffsetElements);
3491 float32x4_t m128_f_tx = vsubq_f32(m128_f_sourceX, vcvtq_f32_u32(m128_u_left));
3492 float32x4_t m128_f_ty = vsubq_f32(m128_f_sourceY, vcvtq_f32_u32(m128_u_top));
3495 m128_f_tx = vmulq_f32(m128_f_tx, vdupq_n_f32(128.0f));
3496 m128_f_ty = vmulq_f32(m128_f_ty, vdupq_n_f32(128.0f));
3498 const uint32x4_t m128_u_tx = vcvtq_u32_f32(vaddq_f32(m128_f_tx, vdupq_n_f32(0.5)));
3499 const uint32x4_t m128_u_ty = vcvtq_u32_f32(vaddq_f32(m128_f_ty, vdupq_n_f32(0.5)));
3501 if constexpr (tChannels > 4u)
3511 const uint32x4_t m128_u_tx_ = vsubq_u32(vdupq_n_u32(128u), m128_u_tx);
3512 const uint32x4_t m128_u_ty_ = vsubq_u32(vdupq_n_u32(128u), m128_u_ty);
3516 const uint32x4_t m128_u_tx_ty_ = vmulq_u32(m128_u_tx_, m128_u_ty_);
3517 const uint32x4_t m128_u_txty_ = vmulq_u32(m128_u_tx, m128_u_ty_);
3518 const uint32x4_t m128_u_tx_ty = vmulq_u32(m128_u_tx_, m128_u_ty);
3519 const uint32x4_t m128_u_txty = vmulq_u32(m128_u_tx, m128_u_ty);
3521 unsigned int tx_ty_s[4];
3522 unsigned int txty_s[4];
3523 unsigned int tx_tys[4];
3524 unsigned int txtys[4];
3527 vst1q_u32(tx_ty_s, m128_u_tx_ty_);
3528 vst1q_u32(txty_s, m128_u_txty_);
3529 vst1q_u32(tx_tys, m128_u_tx_ty);
3530 vst1q_u32(txtys, m128_u_txty);
3532 for (
unsigned int i = 0u; i < 4u; ++i)
3536 ocean_assert(topLeftOffsetsElements[i] < sourceStrideElements * sourceHeight);
3537 ocean_assert(topRightOffsetsElements[i] < sourceStrideElements * sourceHeight);
3538 ocean_assert(bottomLeftOffsetsElements[i] < sourceStrideElements * sourceHeight);
3539 ocean_assert(bottomRightOffsetsElements[i] < sourceStrideElements * sourceHeight);
3541 const uint8_t* topLeft = source + topLeftOffsetsElements[i];
3542 const uint8_t* topRight = source + topRightOffsetsElements[i];
3544 const uint8_t* bottomLeft = source + bottomLeftOffsetsElements[i];
3545 const uint8_t* bottomRight = source + bottomRightOffsetsElements[i];
3547 const unsigned int tx_ty_ = tx_ty_s[i];
3548 const unsigned int txty_ = txty_s[i];
3549 const unsigned int tx_ty = tx_tys[i];
3550 const unsigned int txty = txtys[i];
3552 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
3554 for (
unsigned int n = 0u; n < tChannels; ++n)
3556 ((uint8_t*)targetRow)[n] = uint8_t((topLeft[n] * tx_ty_ + topRight[n] * txty_ + bottomLeft[n] * tx_ty + bottomRight[n] * txty + 8192u) >> 14u);
3561 *targetRow = *bColor;
3569 interpolate4Pixels8BitPerChannelNEON<tChannels>(source, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, m128_u_tx, m128_u_ty, targetRow);
3576 template <
unsigned int tChannels>
3577 void 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)
3579 static_assert(tChannels >= 1u,
"Invalid channel number!");
3581 ocean_assert(input !=
nullptr && output !=
nullptr);
3582 ocean_assert(inputWidth > 0u && inputHeight > 0u);
3583 ocean_assert(outputWidth >= 4u && outputHeight > 0u);
3584 ocean_assert(input_H_output !=
nullptr);
3586 ocean_assert(firstOutputRow + numberOutputRows <= outputHeight);
3588 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
3589 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
3593 uint8_t zeroColor[tChannels] = {uint8_t(0)};
3594 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
3596 unsigned int validPixels[4];
3598 unsigned int topLeftOffsetsElements[4];
3599 unsigned int topRightOffsetsElements[4];
3600 unsigned int bottomLeftOffsetsElements[4];
3601 unsigned int bottomRightOffsetsElements[4];
3603 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
3606 const float32x4_t m128_f_X0 = vdupq_n_f32(
float((*input_H_output)(0, 0)));
3607 const float32x4_t m128_f_X1 = vdupq_n_f32(
float((*input_H_output)(1, 0)));
3608 const float32x4_t m128_f_X2 = vdupq_n_f32(
float((*input_H_output)(2, 0)));
3610 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
3612 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
3636 const float32x4_t m128_f_C0 = vdupq_n_f32(
float((*input_H_output)(0, 1) *
Scalar(y) + (*input_H_output)(0, 2)));
3637 const float32x4_t m128_f_C1 = vdupq_n_f32(
float((*input_H_output)(1, 1) *
Scalar(y) + (*input_H_output)(1, 2)));
3638 const float32x4_t m128_f_C2 = vdupq_n_f32(
float((*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2)));
3641 const float32x4_t m128_f_zero = vdupq_n_f32(0.0f);
3644 const uint32x4_t m128_u_inputStrideElements = vdupq_n_u32(inputStrideElements);
3647 const uint32x4_t m128_u_inputWidth_1 = vdupq_n_u32(inputWidth - 1u);
3648 const uint32x4_t m128_u_inputHeight_1 = vdupq_n_u32(inputHeight - 1u);
3651 const float32x4_t m128_f_inputWidth_1 = vdupq_n_f32(
float(inputWidth - 1u));
3652 const float32x4_t m128_f_inputHeight_1 = vdupq_n_f32(
float(inputHeight - 1u));
3654 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
3656 if (x + 4u > outputWidth)
3661 ocean_assert(x >= 4u && outputWidth > 4u);
3662 const unsigned int newX = outputWidth - 4u;
3664 ocean_assert(x > newX);
3665 outputPixelData -= x - newX;
3670 ocean_assert(!(x + 4u < outputWidth));
3676 float x_0123[4] = {float(x + 0u), float(x + 1u), float(x + 2u), float(x + 3u)};
3677 const float32x4_t m128_f_x_0123 = vld1q_f32(x_0123);
3680 const float32x4_t m128_f_xx = vmlaq_f32(m128_f_C0, m128_f_X0, m128_f_x_0123);
3681 const float32x4_t m128_f_yy = vmlaq_f32(m128_f_C1, m128_f_X1, m128_f_x_0123);
3682 const float32x4_t m128_f_zz = vmlaq_f32(m128_f_C2, m128_f_X2, m128_f_x_0123);
3684 #ifdef USE_DIVISION_ARM64_ARCHITECTURE
3687 const float32x4_t m128_f_inputX = vdivq_f32(m128_f_xx, m128_f_zz);
3688 const float32x4_t m128_f_inputY = vdivq_f32(m128_f_yy, m128_f_zz);
3694 float32x4_t inv_zz_128 = vrecpeq_f32(m128_f_zz);
3695 inv_zz_128 = vmulq_f32(vrecpsq_f32(m128_f_zz, inv_zz_128), inv_zz_128);
3698 const float32x4_t m128_f_inputX = vmulq_f32(m128_f_xx, inv_zz_128);
3699 const float32x4_t m128_f_inputY = vmulq_f32(m128_f_yy, inv_zz_128);
3705 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));
3706 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));
3708 const uint32x4_t m128_u_validPixel = vandq_u32(m128_u_validPixelX, m128_u_validPixelY);
3712 const uint32x2_t m64_u_validPixel = vorr_u32(vget_low_u32(m128_u_validPixel), vget_high_u32(m128_u_validPixel));
3713 if ((vget_lane_u32(m64_u_validPixel, 0) | vget_lane_u32(m64_u_validPixel, 1)) == 0x00000000u)
3716 OCEAN_ALIGN_DATA(16)
unsigned int debugValidPixels[4];
3717 vst1q_u32(debugValidPixels, m128_u_validPixel);
3718 ocean_assert(!(debugValidPixels[0] || debugValidPixels[1] || debugValidPixels[2] || debugValidPixels[3]));
3721 outputPixelData[0] = *bColor;
3722 outputPixelData[1] = *bColor;
3723 outputPixelData[2] = *bColor;
3724 outputPixelData[3] = *bColor;
3726 outputPixelData += 4;
3733 vst1q_u32(validPixels, m128_u_validPixel);
3734 ocean_assert(validPixels[0] || validPixels[1] || validPixels[2] || validPixels[3]);
3739 const uint32x4_t m128_u_left = vcvtq_u32_f32(m128_f_inputX);
3740 const uint32x4_t m128_u_top = vcvtq_u32_f32(m128_f_inputY);
3743 const uint32x4_t m128_u_right = vminq_u32(vaddq_u32(m128_u_left, vdupq_n_u32(1u)), m128_u_inputWidth_1);
3744 const uint32x4_t m128_u_bottom = vminq_u32(vaddq_u32(m128_u_top, vdupq_n_u32(1u)), m128_u_inputHeight_1);
3747 const uint32x4_t m128_u_topLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_top, m128_u_inputStrideElements);
3748 const uint32x4_t m128_u_topRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_top, m128_u_inputStrideElements);
3749 const uint32x4_t m128_u_bottomLeftOffsetElements = vmlaq_u32(vmulq_u32(m128_u_left, constantChannels_u_32x4), m128_u_bottom, m128_u_inputStrideElements);
3750 const uint32x4_t m128_u_bottomRightOffsetElements = vmlaq_u32(vmulq_u32(m128_u_right, constantChannels_u_32x4), m128_u_bottom, m128_u_inputStrideElements);
3753 vst1q_u32(topLeftOffsetsElements, m128_u_topLeftOffsetElements);
3754 vst1q_u32(topRightOffsetsElements, m128_u_topRightOffsetElements);
3755 vst1q_u32(bottomLeftOffsetsElements, m128_u_bottomLeftOffsetElements);
3756 vst1q_u32(bottomRightOffsetsElements, m128_u_bottomRightOffsetElements);
3762 float32x4_t m128_f_tx = vsubq_f32(m128_f_inputX, vcvtq_f32_u32(m128_u_left));
3763 float32x4_t m128_f_ty = vsubq_f32(m128_f_inputY, vcvtq_f32_u32(m128_u_top));
3766 m128_f_tx = vmulq_f32(m128_f_tx, vdupq_n_f32(128.0f));
3767 m128_f_ty = vmulq_f32(m128_f_ty, vdupq_n_f32(128.0f));
3769 const uint32x4_t m128_u_tx = vcvtq_u32_f32(vaddq_f32(m128_f_tx, vdupq_n_f32(0.5)));
3770 const uint32x4_t m128_u_ty = vcvtq_u32_f32(vaddq_f32(m128_f_ty, vdupq_n_f32(0.5)));
3772 if constexpr (tChannels > 4u)
3782 const uint32x4_t m128_u_tx_ = vsubq_u32(vdupq_n_u32(128u), m128_u_tx);
3783 const uint32x4_t m128_u_ty_ = vsubq_u32(vdupq_n_u32(128u), m128_u_ty);
3787 const uint32x4_t m128_u_tx_ty_ = vmulq_u32(m128_u_tx_, m128_u_ty_);
3788 const uint32x4_t m128_u_txty_ = vmulq_u32(m128_u_tx, m128_u_ty_);
3789 const uint32x4_t m128_u_tx_ty = vmulq_u32(m128_u_tx_, m128_u_ty);
3790 const uint32x4_t m128_u_txty = vmulq_u32(m128_u_tx, m128_u_ty);
3792 unsigned int tx_ty_s[4];
3793 unsigned int txty_s[4];
3794 unsigned int tx_tys[4];
3795 unsigned int txtys[4];
3798 vst1q_u32(tx_ty_s, m128_u_tx_ty_);
3799 vst1q_u32(txty_s, m128_u_txty_);
3800 vst1q_u32(tx_tys, m128_u_tx_ty);
3801 vst1q_u32(txtys, m128_u_txty);
3803 for (
unsigned int i = 0u; i < 4u; ++i)
3807 ocean_assert(topLeftOffsetsElements[i] < inputStrideElements * inputHeight);
3808 ocean_assert(topRightOffsetsElements[i] < inputStrideElements * inputHeight);
3809 ocean_assert(bottomLeftOffsetsElements[i] < inputStrideElements * inputHeight);
3810 ocean_assert(bottomRightOffsetsElements[i] < inputStrideElements * inputHeight);
3812 const uint8_t* topLeft = input + topLeftOffsetsElements[i];
3813 const uint8_t* topRight = input + topRightOffsetsElements[i];
3815 const uint8_t* bottomLeft = input + bottomLeftOffsetsElements[i];
3816 const uint8_t* bottomRight = input + bottomRightOffsetsElements[i];
3818 const unsigned int tx_ty_ = tx_ty_s[i];
3819 const unsigned int txty_ = txty_s[i];
3820 const unsigned int tx_ty = tx_tys[i];
3821 const unsigned int txty = txtys[i];
3823 ocean_assert(tx_ty_ + txty_ + tx_ty + txty == 128u * 128u);
3825 for (
unsigned int n = 0u; n < tChannels; ++n)
3827 ((uint8_t*)outputPixelData)[n] = uint8_t((topLeft[n] * tx_ty_ + topRight[n] * txty_ + bottomLeft[n] * tx_ty + bottomRight[n] * txty + 8192u) >> 14u);
3832 *outputPixelData = *bColor;
3840 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, m128_u_tx, m128_u_ty, outputPixelData);
3841 outputPixelData += 4;
3848 OCEAN_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)
3850 ocean_assert(source !=
nullptr);
3851 ocean_assert(targetPositionPixels !=
nullptr);
3863 for (
unsigned int i = 0u; i < 4u; ++i)
3874 pixels[i * 4u + 0u] = borderColor;
3875 pixels[i * 4u + 1u] = borderColor;
3876 pixels[i * 4u + 2u] = borderColor;
3877 pixels[i * 4u + 3u] = borderColor;
3881 static_assert(
sizeof(uint8x16_t) ==
sizeof(pixels),
"Invalid data type!");
3883 const uint8x16_t m128_pixels = vld1q_u8((
const uint8_t*)pixels);
3889 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
3890 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
3895 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
3896 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
3897 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
3898 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
3913 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
3915 const uint32x4_t m128_muliplicationA = vmulq_u32(vandq_u32(vreinterpretq_u32_u8(m128_pixels), m128_maskFirstByte), m128_factorsTopLeft);
3916 const uint32x4_t m128_muliplicationB = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 8), m128_maskFirstByte), m128_factorsTopRight);
3917 const uint32x4_t m128_muliplicationC = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 16), m128_maskFirstByte), m128_factorsBottomLeft);
3918 const uint32x4_t m128_muliplicationD = vmulq_u32(vandq_u32(vshrq_n_u32(vreinterpretq_u32_u8(m128_pixels), 24), m128_maskFirstByte), m128_factorsBottomRight);
3920 const uint32x4_t m128_multiplication = vaddq_u32(vaddq_u32(m128_muliplicationA, m128_muliplicationB), vaddq_u32(m128_muliplicationC, m128_muliplicationD));
3924 const uint8x16_t m128_interpolation = vreinterpretq_u8_u32(vshrq_n_u32(vaddq_u32(m128_multiplication, vdupq_n_u32(8192u)), 14));
3934 #if defined(__aarch64__)
3936 const uint8x8_t m64_mask0 = {0, 4, 1, 1, 1, 1, 1, 1};
3937 const uint8x8_t m64_mask1 = {1, 1, 0, 4, 1, 1, 1, 1};
3939 const uint8x8_t m64_interpolation01 = vtbl1_u8(vget_low_u8(m128_interpolation), m64_mask0);
3940 const uint8x8_t m64_interpolation23 = vtbl1_u8(vget_high_u8(m128_interpolation), m64_mask1);
3942 const uint8x8_t m64_interpolation0123 = vorr_u8(m64_interpolation01, m64_interpolation23);
3944 const uint32_t result = vget_lane_u32(vreinterpret_u32_u8(m64_interpolation0123), 0);
3945 memcpy(targetPositionPixels, &result,
sizeof(uint32_t));
3949 *((uint8_t*)targetPositionPixels + 0) = vgetq_lane_u8(m128_interpolation, 0);
3950 *((uint8_t*)targetPositionPixels + 1) = vgetq_lane_u8(m128_interpolation, 4);
3951 *((uint8_t*)targetPositionPixels + 2) = vgetq_lane_u8(m128_interpolation, 8);
3952 *((uint8_t*)targetPositionPixels + 3) = vgetq_lane_u8(m128_interpolation, 12);
3959 const uint8x16_t factorsLeft_factorsTop_128_u_8x16 = vsubq_u8(vdupq_n_u8(128u), factorsRight_factorsBottom_128_u_8x16);
3961 const uint8x8_t factorsRight_u_8x8 = vget_low_u8(factorsRight_factorsBottom_128_u_8x16);
3962 const uint16x8_t factorsBottom_u_16x8 = vmovl_u8(vget_high_u8(factorsRight_factorsBottom_128_u_8x16));
3964 const uint8x8_t factorsLeft_u_8x8 = vget_low_u8(factorsLeft_factorsTop_128_u_8x16);
3965 const uint16x8_t factorsTop_u_16x8 = vmovl_u8(vget_high_u8(factorsLeft_factorsTop_128_u_8x16));
3967 const uint16x8_t intermediateTop_u_16x8 = vmlal_u8(vmull_u8(topLeft_u_8x8, factorsLeft_u_8x8), topRight_u_8x8, factorsRight_u_8x8);
3968 const uint16x8_t intermediateBottom_u_16x8 = vmlal_u8(vmull_u8(bottomLeft_u_8x8, factorsLeft_u_8x8), bottomRight_u_8x8, factorsRight_u_8x8);
3970 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));
3971 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));
3973 const uint16x8_t result_16x8 = vcombine_u16(vrshrn_n_u32(resultA_32x4, 14), vrshrn_n_u32(resultB_32x4, 14));
3975 const uint8x8_t result_8x8 = vmovn_u16(result_16x8);
3977 vst1_u8(targetPositionPixels, result_8x8);
3981 OCEAN_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)
3983 ocean_assert(source !=
nullptr);
3984 ocean_assert(targetPositionPixels !=
nullptr);
3990 PixelType topPixels[8];
3991 PixelType bottomPixels[8];
4000 for (
unsigned int i = 0u; i < 4u; ++i)
4004 *(topPixels + i * 2u + 0u) = *((
const PixelType*)(source + offsetsTopLeftElements[i]));
4005 *(topPixels + i * 2u + 1u) = *((
const PixelType*)(source + offsetsTopRightElements[i]));
4006 *(bottomPixels + i * 2u + 0u) = *((
const PixelType*)(source + offsetsBottomLeftElements[i]));
4007 *(bottomPixels + i * 2u + 1u) = *((
const PixelType*)(source + offsetsBottomRightElements[i]));
4011 *(topPixels + i * 2u + 0u) = borderColor;
4012 *(topPixels + i * 2u + 1u) = borderColor;
4013 *(bottomPixels + i * 2u + 0u) = borderColor;
4014 *(bottomPixels + i * 2u + 1u) = borderColor;
4018 static_assert(
sizeof(uint32x4_t) ==
sizeof(topPixels),
"Invalid data type!");
4020 const uint32x4_t m128_topPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topPixels));
4021 const uint32x4_t m128_bottomPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomPixels));
4027 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4028 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4033 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4034 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4035 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4036 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4039 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4041 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topPixels, m128_maskFirstByte), m128_factorsTopLeft);
4042 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4044 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4045 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topPixels, 24), m128_maskFirstByte), m128_factorsTopRight));
4047 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4048 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4050 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4051 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomPixels, 24), m128_maskFirstByte), m128_factorsBottomRight));
4056 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4057 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4063 const uint32x4_t m128_interpolation = vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8));
4067 const uint8x8_t m64_mask0 = {0, 1, 4, 5, 2, 2, 2, 2};
4068 const uint8x8_t m64_mask1 = {2, 2, 2, 2, 0, 1, 4, 5};
4070 const uint8x8_t m64_interpolation_low = vtbl1_u8(vget_low_u8(vreinterpretq_u8_u32(m128_interpolation)), m64_mask0);
4071 const uint8x8_t m64_interpolation_high = vtbl1_u8(vget_high_u8(vreinterpretq_u8_u32(m128_interpolation)), m64_mask1);
4073 const uint8x8_t m64_interpolation = vorr_u8(m64_interpolation_low, m64_interpolation_high);
4080 vst1_u8((uint8_t*)targetPositionPixels, m64_interpolation);
4084 OCEAN_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)
4086 ocean_assert(source !=
nullptr);
4087 ocean_assert(targetPositionPixels !=
nullptr);
4091 uint32_t topLeftPixels[4];
4092 uint32_t topRightPixels[4];
4093 uint32_t bottomLeftPixels[4];
4094 uint32_t bottomRightPixels[4];
4102 for (
unsigned int i = 0u; i < 4u; ++i)
4106 memcpy(topLeftPixels + i, source + offsetsTopLeftElements[i],
sizeof(uint8_t) * 3);
4107 memcpy(topRightPixels + i, source + offsetsTopRightElements[i],
sizeof(uint8_t) * 3);
4108 memcpy(bottomLeftPixels + i, source + offsetsBottomLeftElements[i],
sizeof(uint8_t) * 3);
4109 memcpy(bottomRightPixels + i, source + offsetsBottomRightElements[i],
sizeof(uint8_t) * 3);
4113 memcpy(topLeftPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4114 memcpy(topRightPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4115 memcpy(bottomLeftPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4116 memcpy(bottomRightPixels + i, &borderColor,
sizeof(uint8_t) * 3);
4120 static_assert(
sizeof(uint32x4_t) ==
sizeof(topLeftPixels),
"Invalid data type!");
4122 const uint32x4_t m128_topLeftPixels = vld1q_u32(topLeftPixels);
4123 const uint32x4_t m128_topRightPixels = vld1q_u32(topRightPixels);
4124 const uint32x4_t m128_bottomLeftPixels = vld1q_u32(bottomLeftPixels);
4125 const uint32x4_t m128_bottomRightPixels = vld1q_u32(bottomRightPixels);
4131 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4132 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4137 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4138 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4139 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4140 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4143 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4145 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topLeftPixels, m128_maskFirstByte), m128_factorsTopLeft);
4146 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4147 uint32x4_t m128_muliplicationChannel2 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 16), m128_maskFirstByte), m128_factorsTopLeft);
4149 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_topRightPixels, m128_maskFirstByte), m128_factorsTopRight));
4150 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 8), m128_maskFirstByte), m128_factorsTopRight));
4151 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4153 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomLeftPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4154 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4155 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 16), m128_maskFirstByte), m128_factorsBottomLeft));
4157 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomRightPixels, m128_maskFirstByte), m128_factorsBottomRight));
4158 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 8), m128_maskFirstByte), m128_factorsBottomRight));
4159 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4164 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4165 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4166 const uint32x4_t m128_interpolation2 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel2, vdupq_n_u32(8192u)), 14);
4170 const uint32x4_t m128_interpolation = vorrq_u32(vorrq_u32(m128_interpolation0, vshlq_n_u32(m128_interpolation1, 8)), vshlq_n_u32(m128_interpolation2, 16));
4176 uint32_t intermediateBuffer[4];
4177 vst1q_u32(intermediateBuffer, m128_interpolation);
4179 for (
unsigned int i = 0u; i < 4u; ++i)
4181 memcpy(targetPositionPixels + i, intermediateBuffer + i,
sizeof(uint8_t) * 3);
4186 OCEAN_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)
4188 ocean_assert(source !=
nullptr);
4189 ocean_assert(targetPositionPixels !=
nullptr);
4195 PixelType topLeftPixels[4];
4196 PixelType topRightPixels[4];
4197 PixelType bottomLeftPixels[4];
4198 PixelType bottomRightPixels[4];
4206 for (
unsigned int i = 0u; i < 4u; ++i)
4210 *(topLeftPixels + i) = *((
const PixelType*)(source + offsetsTopLeftElements[i]));
4211 *(topRightPixels + i) = *((
const PixelType*)(source + offsetsTopRightElements[i]));
4212 *(bottomLeftPixels + i) = *((
const PixelType*)(source + offsetsBottomLeftElements[i]));
4213 *(bottomRightPixels + i) = *((
const PixelType*)(source + offsetsBottomRightElements[i]));
4217 *(topLeftPixels + i) = borderColor;
4218 *(topRightPixels + i) = borderColor;
4219 *(bottomLeftPixels + i) = borderColor;
4220 *(bottomRightPixels + i) = borderColor;
4224 static_assert(
sizeof(uint32x4_t) ==
sizeof(topLeftPixels),
"Invalid data type!");
4226 const uint32x4_t m128_topLeftPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topLeftPixels));
4227 const uint32x4_t m128_topRightPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)topRightPixels));
4228 const uint32x4_t m128_bottomLeftPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomLeftPixels));
4229 const uint32x4_t m128_bottomRightPixels = vreinterpretq_u32_u8(vld1q_u8((
const uint8_t*)bottomRightPixels));
4235 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4236 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4241 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4242 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4243 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4244 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4247 const uint32x4_t m128_maskFirstByte = vdupq_n_u32(0x000000FFu);
4249 uint32x4_t m128_muliplicationChannel0 = vmulq_u32(vandq_u32(m128_topLeftPixels, m128_maskFirstByte), m128_factorsTopLeft);
4250 uint32x4_t m128_muliplicationChannel1 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 8), m128_maskFirstByte), m128_factorsTopLeft);
4251 uint32x4_t m128_muliplicationChannel2 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 16), m128_maskFirstByte), m128_factorsTopLeft);
4252 uint32x4_t m128_muliplicationChannel3 = vmulq_u32(vandq_u32(vshrq_n_u32(m128_topLeftPixels, 24), m128_maskFirstByte), m128_factorsTopLeft);
4254 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_topRightPixels, m128_maskFirstByte), m128_factorsTopRight));
4255 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 8), m128_maskFirstByte), m128_factorsTopRight));
4256 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 16), m128_maskFirstByte), m128_factorsTopRight));
4257 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_topRightPixels, 24), m128_maskFirstByte), m128_factorsTopRight));
4259 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomLeftPixels, m128_maskFirstByte), m128_factorsBottomLeft));
4260 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 8), m128_maskFirstByte), m128_factorsBottomLeft));
4261 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 16), m128_maskFirstByte), m128_factorsBottomLeft));
4262 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomLeftPixels, 24), m128_maskFirstByte), m128_factorsBottomLeft));
4264 m128_muliplicationChannel0 = vaddq_u32(m128_muliplicationChannel0, vmulq_u32(vandq_u32(m128_bottomRightPixels, m128_maskFirstByte), m128_factorsBottomRight));
4265 m128_muliplicationChannel1 = vaddq_u32(m128_muliplicationChannel1, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 8), m128_maskFirstByte), m128_factorsBottomRight));
4266 m128_muliplicationChannel2 = vaddq_u32(m128_muliplicationChannel2, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 16), m128_maskFirstByte), m128_factorsBottomRight));
4267 m128_muliplicationChannel3 = vaddq_u32(m128_muliplicationChannel3, vmulq_u32(vandq_u32(vshrq_n_u32(m128_bottomRightPixels, 24), m128_maskFirstByte), m128_factorsBottomRight));
4272 const uint32x4_t m128_interpolation0 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel0, vdupq_n_u32(8192u)), 14);
4273 const uint32x4_t m128_interpolation1 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel1, vdupq_n_u32(8192u)), 14);
4274 const uint32x4_t m128_interpolation2 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel2, vdupq_n_u32(8192u)), 14);
4275 const uint32x4_t m128_interpolation3 = vshrq_n_u32(vaddq_u32(m128_muliplicationChannel3, vdupq_n_u32(8192u)), 14);
4279 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)));
4281 vst1q_u8((uint8_t*)targetPositionPixels, vreinterpretq_u8_u32(m128_interpolation));
4284 template <
unsigned int tChannels>
4285 OCEAN_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)
4287 ocean_assert(source !=
nullptr);
4288 ocean_assert(targetPositionPixels !=
nullptr);
4292 unsigned int factorsTopLeft[4];
4293 unsigned int factorsTopRight[4];
4294 unsigned int factorsBottomLeft[4];
4295 unsigned int factorsBottomRight[4];
4301 const uint32x4_t m128_factorsLeft = vsubq_u32(vdupq_n_u32(128u), m128_factorsRight);
4302 const uint32x4_t m128_factorsTop = vsubq_u32(vdupq_n_u32(128u), m128_factorsBottom);
4307 const uint32x4_t m128_factorsTopLeft = vmulq_u32(m128_factorsTop, m128_factorsLeft);
4308 const uint32x4_t m128_factorsTopRight = vmulq_u32(m128_factorsTop, m128_factorsRight);
4309 const uint32x4_t m128_factorsBottomLeft = vmulq_u32(m128_factorsBottom, m128_factorsLeft);
4310 const uint32x4_t m128_factorsBottomRight = vmulq_u32(m128_factorsBottom, m128_factorsRight);
4314 vst1q_u32(factorsTopLeft, m128_factorsTopLeft);
4315 vst1q_u32(factorsTopRight, m128_factorsTopRight);
4316 vst1q_u32(factorsBottomLeft, m128_factorsBottomLeft);
4317 vst1q_u32(factorsBottomRight, m128_factorsBottomRight);
4319 for (
unsigned int i = 0u; i < 4u; ++i)
4323 const uint8_t* topLeft = source + offsetsTopLeftElements[i];
4324 const uint8_t* topRight = source + offsetsTopRightElements[i];
4326 const uint8_t* bottomLeft = source + offsetsBottomLeftElements[i];
4327 const uint8_t* bottomRight = source + offsetsBottomRightElements[i];
4329 const unsigned int& factorTopLeft = factorsTopLeft[i];
4330 const unsigned int& factorTopRight = factorsTopRight[i];
4331 const unsigned int& factorBottomLeft = factorsBottomLeft[i];
4332 const unsigned int& factorBottomRight = factorsBottomRight[i];
4334 for (
unsigned int n = 0u; n < tChannels; ++n)
4336 ((uint8_t*)targetPositionPixels)[n] = (topLeft[n] * factorTopLeft + topRight[n] * factorTopRight + bottomLeft[n] * factorBottomLeft + bottomRight[n] * factorBottomRight + 8192u) >> 14u;
4341 *targetPositionPixels = borderColor;
4344 targetPositionPixels++;
4350 template <
unsigned int tChannels>
4351 inline 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)
4353 static_assert(tChannels >= 1u,
"Invalid channel number!");
4355 ocean_assert(input && output);
4356 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4357 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4359 ocean_assert(outputQuadrantCenterX >= 0 && outputQuadrantCenterX <
Scalar(outputWidth));
4360 ocean_assert(outputQuadrantCenterY >= 0 && outputQuadrantCenterY <
Scalar(outputHeight));
4361 ocean_assert(homographies);
4363 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
4365 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4366 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4368 constexpr uint8_t zeroColor[tChannels] = {uint8_t(0)};
4369 const uint8_t*
const bColor = borderColor ? borderColor : zeroColor;
4371 uint8_t* outputData = output + firstOutputRow * outputStrideElements;
4385 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4387 for (
unsigned int x = 0; x < outputWidth; ++x)
4391 const Scalar _tx = minmax<Scalar>(0, (outputPosition.
x() - left) * invWidth, 1);
4392 const Scalar _ty = minmax<Scalar>(0, (outputPosition.
y() - top) * invHeight, 1);
4396 const Scalar tx = 1 - _tx;
4397 const Scalar ty = 1 - _ty;
4399 const Vector2 inputPositionTopLeft(homographies[0] * outputPosition);
4400 const Vector2 inputPositionTopRight(homographies[1] * outputPosition);
4401 const Vector2 inputPositionBottomLeft(homographies[2] * outputPosition);
4402 const Vector2 inputPositionBottomRight(homographies[3] * outputPosition);
4404 const Scalar tTopLeft = tx * ty;
4405 const Scalar tTopRight = _tx * ty;
4406 const Scalar tBottomLeft = tx * _ty;
4407 const Scalar tBottomRight = _tx * _ty;
4409 const Vector2 inputPosition = inputPositionTopLeft * tTopLeft + inputPositionTopRight * tTopRight
4410 + inputPositionBottomLeft * tBottomLeft + inputPositionBottomRight * tBottomRight;
4412 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4414 for (
unsigned int c = 0u; c < tChannels; ++c)
4416 outputData[c] = bColor[c];
4421 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, outputData);
4424 outputData += tChannels;
4427 outputData += outputPaddingElements;
4431 template <
unsigned int tChannels>
4432 void 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)
4434 static_assert(tChannels >= 1u,
"Invalid channel number!");
4436 ocean_assert(input !=
nullptr && output !=
nullptr);
4437 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4438 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4439 ocean_assert(input_H_output !=
nullptr);
4441 ocean_assert_and_suppress_unused(firstOutputRow + numberOutputRows <= outputHeight, outputHeight);
4443 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
4444 const unsigned int outputMaskStrideElements = outputWidth + outputMaskPaddingElements;
4446 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4447 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4451 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4453 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4454 uint8_t* outputMaskData = outputMask + y * outputMaskStrideElements;
4478 const Scalar X2 = (*input_H_output)(2, 0);
4479 const Scalar constValue2 = (*input_H_output)(2, 1) *
Scalar(y) + (*input_H_output)(2, 2);
4481 for (
unsigned int x = 0; x < outputWidth; ++x)
4487 ocean_assert(inputPosition.
isEqual(debugInputPosition,
Scalar(0.01)));
4490 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4492 *outputMaskData = 0xFF - maskValue;
4496 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
4497 *outputMaskData = maskValue;
4506 template <
unsigned int tChannels>
4507 inline 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)
4509 static_assert(tChannels >= 1u,
"Invalid channel number!");
4511 ocean_assert(input && output);
4512 ocean_assert(inputWidth > 0u && inputHeight > 0u);
4513 ocean_assert(outputWidth > 0u && outputHeight > 0u);
4515 ocean_assert(outputQuadrantCenterX >= 0 && outputQuadrantCenterX <
Scalar(outputWidth));
4516 ocean_assert(outputQuadrantCenterY >= 0 && outputQuadrantCenterY <
Scalar(outputHeight));
4517 ocean_assert(homographies);
4519 const unsigned int outputStrideElements = tChannels * outputWidth + outputPaddingElements;
4520 const unsigned int outputMaskStrideElements = outputWidth + outputMaskPaddingElements;
4522 const Scalar scalarInputWidth_1 =
Scalar(inputWidth - 1u);
4523 const Scalar scalarInputHeight_1 =
Scalar(inputHeight - 1u);
4525 uint8_t* outputData = output + firstOutputRow * outputStrideElements;
4526 outputMask += firstOutputRow * outputMaskStrideElements;
4540 for (
unsigned int y = firstOutputRow; y < firstOutputRow + numberOutputRows; ++y)
4542 for (
unsigned int x = 0u; x < outputWidth; ++x)
4546 const Scalar _tx = minmax<Scalar>(0, (outputPosition.
x() - left) * invWidth, 1);
4547 const Scalar _ty = minmax<Scalar>(0, (outputPosition.
y() - top) * invHeight, 1);
4551 const Scalar tx = 1 - _tx;
4552 const Scalar ty = 1 - _ty;
4554 const Vector2 inputPositionTopLeft(homographies[0] * outputPosition);
4555 const Vector2 inputPositionTopRight(homographies[1] * outputPosition);
4556 const Vector2 inputPositionBottomLeft(homographies[2] * outputPosition);
4557 const Vector2 inputPositionBottomRight(homographies[3] * outputPosition);
4559 const Scalar tTopLeft = tx * ty;
4560 const Scalar tTopRight = _tx * ty;
4561 const Scalar tBottomLeft = tx * _ty;
4562 const Scalar tBottomRight = _tx * _ty;
4564 const Vector2 inputPosition = inputPositionTopLeft * tTopLeft + inputPositionTopRight * tTopRight
4565 + inputPositionBottomLeft * tBottomLeft + inputPositionBottomRight * tBottomRight;
4567 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4569 *outputMask = 0xFFu - maskValue;
4573 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, outputData);
4574 *outputMask = maskValue;
4577 outputData += tChannels;
4581 outputData += outputPaddingElements;
4582 outputMask += outputMaskPaddingElements;
4586 template <
unsigned int tChannels>
4587 void 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)
4589 static_assert(tChannels >= 1u,
"Invalid channel number!");
4591 ocean_assert(inputCamera && outputCamera && normalizedHomography);
4592 ocean_assert(input && output);
4594 ocean_assert(firstRow + numberRows <= outputCamera->height());
4596 const unsigned int outputStrideElements = tChannels * outputCamera->
width() + outputPaddingElements;
4605 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
4606 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4608 uint8_t* outputData = output + firstRow * outputStrideElements;
4610 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4612 for (
unsigned int x = 0; x < outputCamera->
width(); ++x)
4616 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4618 *((PixelType*)outputData) = *bColor;
4622 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputCamera->
width(), inputCamera->
height(), inputPaddingElements, inputPosition, outputData);
4625 outputData += tChannels;
4628 outputData += outputPaddingElements;
4632 template <
unsigned int tChannels>
4633 void 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)
4635 static_assert(tChannels >= 1u,
"Invalid channel number!");
4637 ocean_assert(inputCamera !=
nullptr && outputCamera !=
nullptr && normalizedHomography !=
nullptr);
4638 ocean_assert(input !=
nullptr && output !=
nullptr);
4640 ocean_assert(firstRow + numberRows <= outputCamera->height());
4642 const unsigned int outputStrideElements = outputCamera->
width() * tChannels + outputPaddingElements;
4643 const unsigned int outputMaskStrideElements = outputCamera->
width() + outputMaskPaddingElements;
4650 uint8_t* outputData = output + firstRow * outputStrideElements;
4651 outputMask += firstRow * outputMaskStrideElements;
4653 constexpr
bool useDistortionParameters =
true;
4655 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4657 for (
unsigned int x = 0; x < outputCamera->
width(); ++x)
4661 if (inputPosition.
x() <
Scalar(0) || inputPosition.
x() > scalarInputWidth_1 || inputPosition.
y() <
Scalar(0) || inputPosition.
y() > scalarInputHeight_1)
4663 *outputMask = 0xFF - maskValue;
4667 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputCamera->
width(), inputCamera->
height(), inputPaddingElements, inputPosition, outputData);
4668 *outputMask = maskValue;
4671 outputData += tChannels;
4675 outputData += outputPaddingElements;
4676 outputMask += outputMaskPaddingElements;
4680 template <
unsigned int tChannels>
4681 void 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)
4683 static_assert(tChannels >= 1u,
"Invalid channel number!");
4685 ocean_assert(input_LT_output !=
nullptr);
4686 ocean_assert(input !=
nullptr && output !=
nullptr);
4688 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4689 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4693 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
4694 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4696 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
4698 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
4700 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4705 Memory rowLookupMemory = Memory::create<Vector2>(columns);
4708 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4712 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4714 for (
unsigned int x = 0u; x < columns; ++x)
4716 const Vector2& lookupValue = rowLookupData[x];
4720 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
y() >=
Scalar(0) && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
4722 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
4726 *outputData = *bColor;
4734 template <
typename T,
unsigned int tChannels>
4735 void 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)
4737 static_assert(tChannels >= 1u,
"Invalid channel number!");
4739 ocean_assert((!std::is_same<uint8_t, T>::value));
4741 ocean_assert(input_LT_output !=
nullptr);
4742 ocean_assert(input !=
nullptr && output !=
nullptr);
4744 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4745 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4749 const T zeroColor[tChannels] = {T(0)};
4750 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
4752 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
4754 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
4756 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4761 Memory rowLookupMemory = Memory::create<Vector2>(columns);
4764 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4768 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
4770 for (
unsigned int x = 0u; x < columns; ++x)
4772 const Vector2& lookupValue = rowLookupData[x];
4776 if (inputPosition.
x() >=
Scalar(0) && inputPosition.
y() >=
Scalar(0) && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
4778 interpolatePixel<T, T, tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (T*)(outputData));
4782 *outputData = *bColor;
4790 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
4793 inline 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)
4795 ocean_assert(input_LT_output !=
nullptr);
4796 ocean_assert(input !=
nullptr && output !=
nullptr);
4798 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4799 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
4801 typedef uint8_t PixelType;
4803 const uint8x16_t constantBorderColor_u_8x16 = vdupq_n_u8(borderColor ? *borderColor : 0u);
4805 const unsigned int outputWidth = (
unsigned int)(input_LT_output->
sizeX());
4806 ocean_assert(outputWidth >= 8u);
4808 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
4810 const unsigned int inputStrideElements = inputWidth + inputPaddingElements;
4811 const unsigned int outputStrideElements = outputWidth + outputPaddingElements;
4813 Memory rowLookupMemory = Memory::create<VectorF2>(outputWidth);
4816 const float32x4_t constantZero_f_32x4 = vdupq_n_f32(0.0f);
4817 const float32x4_t constantEight_f_32x4 = vdupq_n_f32(8.0f);
4820 const float f_01234567[8] = {0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f};
4821 const float32x4_t conststant0123_f_32x4 = vld1q_f32(f_01234567 + 0);
4822 const float32x4_t conststant4567_f_32x4 = vld1q_f32(f_01234567 + 4);
4824 const float32x4_t constant128_f_32x4 = vdupq_n_f32(128.0f);
4826 const uint32x4_t constantOne_u_32x4 = vdupq_n_u32(1u);
4828 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(1u);
4830 const float32x4_t constantInputWidth1_f_32x4 = vdupq_n_f32(
float(inputWidth - 1u));
4831 const float32x4_t constantInputHeight1_f_32x4 = vdupq_n_f32(
float(inputHeight - 1u));
4833 const uint32x4_t constantInputStrideElements_u_32x4 = vdupq_n_u32(inputStrideElements);
4834 const uint32x4_t constantInputHeight1_u_32x4 = vdupq_n_u32(inputHeight - 1u);
4836 unsigned int validPixels[8];
4838 unsigned int topLeftOffsetsElements[8];
4839 unsigned int bottomLeftOffsetsElements[8];
4843 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
4845 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
4849 float32x4_t additionalInputOffsetX0123_f_32x4 = conststant0123_f_32x4;
4850 float32x4_t additionalInputOffsetX4567_f_32x4 = conststant4567_f_32x4;
4852 const float32x4_t additionalInputOffsetY_f_32x4 = vdupq_n_f32(
float(y));
4854 for (
unsigned int x = 0u; x < outputWidth; x += 8u)
4856 if (x + 8u > outputWidth)
4861 ocean_assert(x >= 8u && outputWidth > 8u);
4862 const unsigned int newX = outputWidth - 8u;
4864 ocean_assert(x > newX);
4865 const unsigned int xOffset = x - newX;
4867 outputPixelData -= xOffset;
4871 additionalInputOffsetX0123_f_32x4 = vsubq_f32(additionalInputOffsetX0123_f_32x4, vdupq_n_f32(
float(xOffset)));
4872 additionalInputOffsetX4567_f_32x4 = vsubq_f32(additionalInputOffsetX4567_f_32x4, vdupq_n_f32(
float(xOffset)));
4878 ocean_assert(!(x + 8u < outputWidth));
4881 const float32x4x2_t inputPositions0123_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x + 0u));
4882 const float32x4x2_t inputPositions4567_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x + 4u));
4884 float32x4_t inputPositionsX0123_f_32x4 = inputPositions0123_f_32x4x2.val[0];
4885 float32x4_t inputPositionsY0123_f_32x4 = inputPositions0123_f_32x4x2.val[1];
4887 float32x4_t inputPositionsX4567_f_32x4 = inputPositions4567_f_32x4x2.val[0];
4888 float32x4_t inputPositionsY4567_f_32x4 = inputPositions4567_f_32x4x2.val[1];
4892 inputPositionsX0123_f_32x4 = vaddq_f32(inputPositionsX0123_f_32x4, additionalInputOffsetX0123_f_32x4);
4893 inputPositionsY0123_f_32x4 = vaddq_f32(inputPositionsY0123_f_32x4, additionalInputOffsetY_f_32x4);
4895 inputPositionsX4567_f_32x4 = vaddq_f32(inputPositionsX4567_f_32x4, additionalInputOffsetX4567_f_32x4);
4896 inputPositionsY4567_f_32x4 = vaddq_f32(inputPositionsY4567_f_32x4, additionalInputOffsetY_f_32x4);
4898 additionalInputOffsetX0123_f_32x4 = vaddq_f32(additionalInputOffsetX0123_f_32x4, constantEight_f_32x4);
4899 additionalInputOffsetX4567_f_32x4 = vaddq_f32(additionalInputOffsetX4567_f_32x4, constantEight_f_32x4);
4903 const uint32x4_t validPixelsX0123_u_32x4 = vandq_u32(vcltq_f32(inputPositionsX0123_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX0123_f_32x4, constantZero_f_32x4));
4904 const uint32x4_t validPixelsX4567_u_32x4 = vandq_u32(vcltq_f32(inputPositionsX4567_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX4567_f_32x4, constantZero_f_32x4));
4906 const uint32x4_t validPixelsY0123_u_32x4 = vandq_u32(vcltq_f32(inputPositionsY0123_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY0123_f_32x4, constantZero_f_32x4));
4907 const uint32x4_t validPixelsY4567_u_32x4 = vandq_u32(vcltq_f32(inputPositionsY4567_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY4567_f_32x4, constantZero_f_32x4));
4909 const uint32x4_t validPixels0123_u_32x4 = vandq_u32(validPixelsX0123_u_32x4, validPixelsY0123_u_32x4);
4910 const uint32x4_t validPixels4567_u_32x4 = vandq_u32(validPixelsX4567_u_32x4, validPixelsY4567_u_32x4);
4912 vst1q_u32(validPixels + 0, validPixels0123_u_32x4);
4913 vst1q_u32(validPixels + 4, validPixels4567_u_32x4);
4916 const uint32x4_t inputPositionsLeft0123_u_32x4 = vcvtq_u32_f32(inputPositionsX0123_f_32x4);
4917 const uint32x4_t inputPositionsLeft4567_u_32x4 = vcvtq_u32_f32(inputPositionsX4567_f_32x4);
4919 const uint32x4_t inputPositionsTop0123_u_32x4 = vcvtq_u32_f32(inputPositionsY0123_f_32x4);
4920 const uint32x4_t inputPositionsTop4567_u_32x4 = vcvtq_u32_f32(inputPositionsY4567_f_32x4);
4922 const uint32x4_t inputPositionsBottom0123_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop0123_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
4923 const uint32x4_t inputPositionsBottom4567_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop4567_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
4926 const uint32x4_t topLeftOffsetsElements0123_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft0123_u_32x4, constantChannels_u_32x4), inputPositionsTop0123_u_32x4, constantInputStrideElements_u_32x4);
4927 vst1q_u32(topLeftOffsetsElements + 0, topLeftOffsetsElements0123_u_32x4);
4928 const uint32x4_t topLeftOffsetsElements4567_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft4567_u_32x4, constantChannels_u_32x4), inputPositionsTop4567_u_32x4, constantInputStrideElements_u_32x4);
4929 vst1q_u32(topLeftOffsetsElements + 4, topLeftOffsetsElements4567_u_32x4);
4931 const uint32x4_t bottomLeftOffsetsElements0123_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft0123_u_32x4, constantChannels_u_32x4), inputPositionsBottom0123_u_32x4, constantInputStrideElements_u_32x4);
4932 vst1q_u32(bottomLeftOffsetsElements + 0, bottomLeftOffsetsElements0123_u_32x4);
4933 const uint32x4_t bottomLeftOffsetsElements4567_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft4567_u_32x4, constantChannels_u_32x4), inputPositionsBottom4567_u_32x4, constantInputStrideElements_u_32x4);
4934 vst1q_u32(bottomLeftOffsetsElements + 4, bottomLeftOffsetsElements4567_u_32x4);
4938 float32x4_t tx0123_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX0123_f_32x4, vcvtq_f32_u32(inputPositionsLeft0123_u_32x4)), constant128_f_32x4);
4939 float32x4_t tx4567_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsX4567_f_32x4, vcvtq_f32_u32(inputPositionsLeft4567_u_32x4)), constant128_f_32x4);
4941 float32x4_t ty0123_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY0123_f_32x4, vcvtq_f32_u32(inputPositionsTop0123_u_32x4)), constant128_f_32x4);
4942 float32x4_t ty4567_f_32x4 = vmulq_f32(vsubq_f32(inputPositionsY4567_f_32x4, vcvtq_f32_u32(inputPositionsTop4567_u_32x4)), constant128_f_32x4);
4944 const uint32x4_t tx0123_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx0123_f_32x4, vdupq_n_f32(0.5)));
4945 const uint32x4_t tx4567_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx4567_f_32x4, vdupq_n_f32(0.5)));
4947 const uint32x4_t ty0123_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty0123_f_32x4, vdupq_n_f32(0.5)));
4948 const uint32x4_t ty4567_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty4567_f_32x4, vdupq_n_f32(0.5)));
4950 const uint16x8_t tx01234567_128_u_16x8 = vcombine_u16(vmovn_u32(tx0123_128_u_32x4), vmovn_u32(tx4567_128_u_32x4));
4951 const uint16x8_t ty01234567_128_u_16x8 = vcombine_u16(vmovn_u32(ty0123_128_u_32x4), vmovn_u32(ty4567_128_u_32x4));
4953 const uint8x16_t tx_ty_128_u_8x16 = vcombine_u8(vmovn_u16(tx01234567_128_u_16x8), vmovn_u16(ty01234567_128_u_16x8));
4956 vst1q_u8(pixels + 0, constantBorderColor_u_8x16);
4957 vst1q_u8(pixels + 16, constantBorderColor_u_8x16);
4959 struct LeftRightPixel
4965 static_assert(
sizeof(LeftRightPixel) == 2,
"Invalid data type!");
4969 for (
unsigned int i = 0u; i < 8u; ++i)
4973 ocean_assert((topLeftOffsetsElements[i] % inputStrideElements) < inputWidth - 1u);
4974 ocean_assert((bottomLeftOffsetsElements[i] % inputStrideElements) < inputWidth - 1u);
4976 ((LeftRightPixel*)pixels)[0u + i] = *(LeftRightPixel*)(input + topLeftOffsetsElements[i]);
4977 ((LeftRightPixel*)pixels)[8u + i] = *(LeftRightPixel*)(input + bottomLeftOffsetsElements[i]);
4981 const uint8x8x2_t topLeft_topRight_u_8x8x2 = vld2_u8(pixels);
4982 const uint8x8x2_t bottomLeft_bottomRight_u_8x8x2 = vld2_u8(pixels + 16);
4984 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);
4986 outputPixelData += 8;
4991 template <
unsigned int tChannels>
4992 void 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)
4994 ocean_assert(input_LT_output !=
nullptr);
4995 ocean_assert(input !=
nullptr && output !=
nullptr);
4997 ocean_assert(inputWidth != 0u && inputHeight != 0u);
4998 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
5002 const uint8_t zeroColor[tChannels] = {uint8_t(0)};
5003 const PixelType*
const bColor = borderColor ? (PixelType*)borderColor : (PixelType*)zeroColor;
5005 const unsigned int outputWidth = (
unsigned int)(input_LT_output->
sizeX());
5006 ocean_assert(outputWidth >= 4u);
5008 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5010 const unsigned int inputStrideElements = inputWidth * tChannels + inputPaddingElements;
5011 const unsigned int outputStrideElements = outputWidth * tChannels + outputPaddingElements;
5013 Memory rowLookupMemory = Memory::create<VectorF2>(outputWidth);
5016 const float32x4_t constantZero_f_32x4 = vdupq_n_f32(0.0f);
5017 const float32x4_t constantFour_f_32x4 = vdupq_n_f32(4.0f);
5020 const float f_0123[4] = {0.0f, 1.0f, 2.0f, 3.0f};
5021 float32x4_t conststant0123_f_32x4 = vld1q_f32(f_0123);
5023 const uint32x4_t constantOne_u_32x4 = vdupq_n_u32(1u);
5025 const uint32x4_t constantChannels_u_32x4 = vdupq_n_u32(tChannels);
5027 const float32x4_t constantInputWidth1_f_32x4 = vdupq_n_f32(
float(inputWidth - 1u));
5028 const float32x4_t constantInputHeight1_f_32x4 = vdupq_n_f32(
float(inputHeight - 1u));
5030 const uint32x4_t constantInputStrideElements_u_32x4 = vdupq_n_u32(inputStrideElements);
5031 const uint32x4_t constantInputWidth1_u_32x4 = vdupq_n_u32(inputWidth - 1u);
5032 const uint32x4_t constantInputHeight1_u_32x4 = vdupq_n_u32(inputHeight - 1u);
5034 unsigned int validPixels[4];
5036 unsigned int topLeftOffsetsElements[4];
5037 unsigned int topRightOffsetsElements[4];
5038 unsigned int bottomLeftOffsetsElements[4];
5039 unsigned int bottomRightOffsetsElements[4];
5041 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5043 PixelType* outputPixelData = (PixelType*)(output + y * outputStrideElements);
5047 float32x4_t additionalInputOffsetX_f_32x4 = conststant0123_f_32x4;
5048 const float32x4_t additionalInputOffsetY_f_32x4 = vdupq_n_f32(
float(y));
5050 for (
unsigned int x = 0u; x < outputWidth; x += 4u)
5052 if (x + 4u > outputWidth)
5057 ocean_assert(x >= 4u && outputWidth > 4u);
5058 const unsigned int newX = outputWidth - 4u;
5060 ocean_assert(x > newX);
5061 const unsigned int xOffset = x - newX;
5063 outputPixelData -= xOffset;
5067 additionalInputOffsetX_f_32x4 = vsubq_f32(additionalInputOffsetX_f_32x4, vdupq_n_f32(
float(xOffset)));
5073 ocean_assert(!(x + 4u < outputWidth));
5076 const float32x4x2_t inputPositions_f_32x4x2 = vld2q_f32((
const float*)(rowLookupData + x));
5078 float32x4_t inputPositionsX_f_32x4 = inputPositions_f_32x4x2.val[0];
5079 float32x4_t inputPositionsY_f_32x4 = inputPositions_f_32x4x2.val[1];
5083 inputPositionsX_f_32x4 = vaddq_f32(inputPositionsX_f_32x4, additionalInputOffsetX_f_32x4);
5084 inputPositionsY_f_32x4 = vaddq_f32(inputPositionsY_f_32x4, additionalInputOffsetY_f_32x4);
5086 additionalInputOffsetX_f_32x4 = vaddq_f32(additionalInputOffsetX_f_32x4, constantFour_f_32x4);
5090 const uint32x4_t validPixelsX_u_32x4 = vandq_u32(vcleq_f32(inputPositionsX_f_32x4, constantInputWidth1_f_32x4), vcgeq_f32(inputPositionsX_f_32x4, constantZero_f_32x4));
5091 const uint32x4_t validPixelsY_u_32x4 = vandq_u32(vcleq_f32(inputPositionsY_f_32x4, constantInputHeight1_f_32x4), vcgeq_f32(inputPositionsY_f_32x4, constantZero_f_32x4));
5093 const uint32x4_t validPixels_u_32x4 = vandq_u32(validPixelsX_u_32x4, validPixelsY_u_32x4);
5095 vst1q_u32(validPixels, validPixels_u_32x4);
5097 const uint32x4_t inputPositionsLeft_u_32x4 = vcvtq_u32_f32(inputPositionsX_f_32x4);
5098 const uint32x4_t inputPositionsTop_u_32x4 = vcvtq_u32_f32(inputPositionsY_f_32x4);
5100 const uint32x4_t inputPositionsRight_u_32x4 = vminq_u32(vaddq_u32(inputPositionsLeft_u_32x4, constantOne_u_32x4), constantInputWidth1_u_32x4);
5101 const uint32x4_t inputPositionsBottom_u_32x4 = vminq_u32(vaddq_u32(inputPositionsTop_u_32x4, constantOne_u_32x4), constantInputHeight1_u_32x4);
5103 const uint32x4_t topLeftOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft_u_32x4, constantChannels_u_32x4), inputPositionsTop_u_32x4, constantInputStrideElements_u_32x4);
5104 const uint32x4_t topRightOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsRight_u_32x4, constantChannels_u_32x4), inputPositionsTop_u_32x4, constantInputStrideElements_u_32x4);
5105 const uint32x4_t bottomLeftOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsLeft_u_32x4, constantChannels_u_32x4), inputPositionsBottom_u_32x4, constantInputStrideElements_u_32x4);
5106 const uint32x4_t bottomRightOffsetsElements_u_32x4 = vmlaq_u32(vmulq_u32(inputPositionsRight_u_32x4, constantChannels_u_32x4), inputPositionsBottom_u_32x4, constantInputStrideElements_u_32x4);
5108 vst1q_u32(topLeftOffsetsElements, topLeftOffsetsElements_u_32x4);
5109 vst1q_u32(topRightOffsetsElements, topRightOffsetsElements_u_32x4);
5110 vst1q_u32(bottomLeftOffsetsElements, bottomLeftOffsetsElements_u_32x4);
5111 vst1q_u32(bottomRightOffsetsElements, bottomRightOffsetsElements_u_32x4);
5114 float32x4_t tx_f_32x4 = vsubq_f32(inputPositionsX_f_32x4, vcvtq_f32_u32(inputPositionsLeft_u_32x4));
5115 float32x4_t ty_f_32x4 = vsubq_f32(inputPositionsY_f_32x4, vcvtq_f32_u32(inputPositionsTop_u_32x4));
5118 tx_f_32x4 = vmulq_f32(tx_f_32x4, vdupq_n_f32(128.0f));
5119 ty_f_32x4 = vmulq_f32(ty_f_32x4, vdupq_n_f32(128.0f));
5121 const uint32x4_t tx_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(tx_f_32x4, vdupq_n_f32(0.5)));
5122 const uint32x4_t ty_128_u_32x4 = vcvtq_u32_f32(vaddq_f32(ty_f_32x4, vdupq_n_f32(0.5)));
5124 interpolate4Pixels8BitPerChannelNEON<tChannels>(input, topLeftOffsetsElements, topRightOffsetsElements, bottomLeftOffsetsElements, bottomRightOffsetsElements, validPixels, *bColor, tx_128_u_32x4, ty_128_u_32x4, outputPixelData);
5126 outputPixelData += 4;
5133 template <
unsigned int tChannels>
5134 void 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)
5136 ocean_assert(input_LT_output !=
nullptr);
5137 ocean_assert(input !=
nullptr && output !=
nullptr);
5139 ocean_assert(inputWidth != 0u && inputHeight != 0u);
5140 ocean_assert(firstRow + numberRows <= input_LT_output->sizeY());
5144 const unsigned int columns = (
unsigned int)(input_LT_output->
sizeX());
5146 const unsigned int outputStrideElements = tChannels * columns + outputPaddingElements;
5147 const unsigned int outputMaskStrideElements = columns + outputMaskPaddingElements;
5149 static_assert(std::is_same<Vector2, LookupTable::Type>::value,
"Invalid data type!");
5154 Memory rowLookupMemory = Memory::create<Vector2>(columns);
5157 for (
unsigned int y = firstRow; y < firstRow + numberRows; ++y)
5161 PixelType* outputData = (PixelType*)(output + y * outputStrideElements);
5162 uint8_t* outputMaskData = outputMask + y * outputMaskStrideElements;
5164 for (
unsigned int x = 0u; x < columns; ++x)
5166 const Vector2& lookupValue = rowLookupData[x];
5170 if (inputPosition.
x() >= 0 && inputPosition.
y() >= 0 && inputPosition.
x() <= inputWidth1 && inputPosition.
y() <= inputHeight1)
5172 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(input, inputWidth, inputHeight, inputPaddingElements, inputPosition, (uint8_t*)(outputData));
5173 *outputMaskData = maskValue;
5177 *outputMaskData = 0xFFu - maskValue;
5186 template <
unsigned int tChannels>
5187 void 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)
5189 ocean_assert(source !=
nullptr && target !=
nullptr);
5190 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
5191 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
5192 ocean_assert(sourceX_s_targetX > 0.0);
5193 ocean_assert(sourceY_s_targetY > 0.0);
5195 if (sourceWidth == targetWidth && sourceHeight == targetHeight)
5197 FrameConverter::subFrame<uint8_t>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, 0u, 0u, 0u, 0u, sourceWidth, sourceHeight, sourcePaddingElements, targetPaddingElements);
5201 if (worker && sourceWidth * tChannels >= 16u && targetWidth >= 8u)
5203 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5204 if (sourceWidth <= 65535u && sourceHeight <= 65535u && targetWidth <= 65535u && targetHeight <= 65535u)
5206 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);
5210 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);
5215 if (sourceWidth * tChannels >= 16u && targetWidth >= 8u)
5217 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5218 if (sourceWidth <= 65535u && sourceHeight <= 65535u && targetWidth <= 65535u && targetHeight <= 65535u)
5220 scale8BitPerChannelSubset7BitPrecisionNEON(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, tChannels, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
5226 scale8BitPerChannelSubset<tChannels>(source, target, sourceWidth, sourceHeight, targetWidth, targetHeight, sourceX_s_targetX, sourceY_s_targetY, sourcePaddingElements, targetPaddingElements, 0u, targetHeight);
5230 template <
unsigned int tChannels>
5231 void 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)
5233 ocean_assert(source !=
nullptr && target !=
nullptr);
5234 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
5235 ocean_assert_and_suppress_unused(targetWidth >= 1u && targetHeight >= 1u, targetHeight);
5236 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5238 const Scalar sourceX_T_targetX =
Scalar(sourceX_s_targetX);
5239 const Scalar sourceY_T_targetY =
Scalar(sourceY_s_targetY);
5287 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
5289 const Scalar sourceX_T_targetXOffset = sourceX_T_targetX *
Scalar(0.5) -
Scalar(0.5);
5290 const Scalar sourceY_T_targetYOffset = sourceY_T_targetY *
Scalar(0.5) -
Scalar(0.5);
5293 const Scalar sourceHeight_1 =
Scalar(sourceHeight - 1u);
5295 target += (targetWidth * tChannels + targetPaddingElements) * firstTargetRow;
5297 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5300 ocean_assert(sy >=
Scalar(0) && sy <
Scalar(sourceHeight));
5302 const unsigned int sTop = (
unsigned int)sy;
5303 ocean_assert(sy >=
Scalar(sTop));
5306 ocean_assert(ty >= 0 && ty <= 1);
5308 const unsigned int factorBottom = (
unsigned int)(ty *
Scalar(128) +
Scalar(0.5));
5309 const unsigned int factorTop = 128u - factorBottom;
5311 const uint8_t*
const sourceTop = source + sourceStrideElements * sTop;
5312 const uint8_t*
const sourceBottom = (sTop + 1u < sourceHeight) ? sourceTop + sourceStrideElements : sourceTop;
5314 for (
unsigned int x = 0; x < targetWidth; ++x)
5317 ocean_assert(sx >=
Scalar(0) && sx <
Scalar(sourceWidth));
5319 const unsigned int sLeft = (
unsigned int)sx;
5320 ocean_assert(sx >=
Scalar(sLeft));
5323 ocean_assert(tx >= 0 && tx <= 1);
5325 const unsigned int factorRight = (
unsigned int)(tx *
Scalar(128) +
Scalar(0.5));
5326 const unsigned int factorLeft = 128u - factorRight;
5328 const unsigned int sourceRightOffset = sLeft + 1u < sourceWidth ? tChannels : 0u;
5330 const uint8_t*
const sourceTopLeft = sourceTop + sLeft * tChannels;
5331 const uint8_t*
const sourceBottomLeft = sourceBottom + sLeft * tChannels;
5333 const unsigned int factorTopLeft = factorTop * factorLeft;
5334 const unsigned int factorTopRight = factorTop * factorRight;
5335 const unsigned int factorBottomLeft = factorBottom * factorLeft;
5336 const unsigned int factorBottomRight = factorBottom * factorRight;
5338 for (
unsigned int n = 0u; n < tChannels; ++n)
5340 target[n] = (uint8_t)((sourceTopLeft[n] * factorTopLeft + sourceTopLeft[sourceRightOffset + n] * factorTopRight
5341 + sourceBottomLeft[n] * factorBottomLeft + sourceBottomLeft[sourceRightOffset + n] * factorBottomRight + 8192u) >> 14u);
5344 target += tChannels;
5347 target += targetPaddingElements;
5351 template <
typename T>
5354 ocean_assert(sourceRowTop !=
nullptr);
5355 ocean_assert(sourceRowBottom !=
nullptr);
5356 ocean_assert(targetRow !=
nullptr);
5357 ocean_assert(elements >= 1u);
5358 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
5362 const FloatType internalFactorBottom = FloatType(factorBottom);
5363 const FloatType internalFactorTop = FloatType(1.0f - factorBottom);
5365 for (
unsigned int n = 0u; n < elements; ++n)
5367 targetRow[n] = T(FloatType(sourceRowTop[n]) * internalFactorTop + FloatType(sourceRowBottom[n]) * internalFactorBottom);
5371 template <
typename T,
unsigned int tChannels>
5374 static_assert(tChannels != 0u,
"Invalid channel number!");
5376 ocean_assert(extendedSourceRow !=
nullptr);
5377 ocean_assert(targetRow !=
nullptr);
5378 ocean_assert(targetWidth >= 1u);
5379 ocean_assert(interpolationLocations !=
nullptr);
5380 ocean_assert(interpolationFactorsRight !=
nullptr);
5381 ocean_assert(channels == tChannels);
5385 for (
unsigned int x = 0u; x < targetWidth; ++x)
5387 const FloatType internalFactorRight = FloatType(interpolationFactorsRight[x]);
5388 ocean_assert(internalFactorRight >= FloatType(0) && internalFactorRight <= FloatType(1));
5390 const FloatType internalFactorLeft = FloatType(1.0f - interpolationFactorsRight[x]);
5392 const unsigned int& leftLocation = interpolationLocations[x];
5393 const unsigned int rightLocation = leftLocation + tChannels;
5395 for (
unsigned int n = 0u; n < tChannels; ++n)
5397 targetRow[x * tChannels + n] = T(FloatType(extendedSourceRow[leftLocation + n]) * internalFactorLeft + FloatType(extendedSourceRow[rightLocation + n]) * internalFactorRight);
5402 #if defined(OCEAN_HARDWARE_NEON_VERSION) && OCEAN_HARDWARE_NEON_VERSION >= 10
5404 #ifdef OCEAN_WE_KEEP_THIS_IMPLEMENTATION_AS_WE_NEED_THIS_TO_FOR_A_NEW_NEON_IMPLEMENTATION
5407 inline 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)
5409 ocean_assert(source !=
nullptr && target !=
nullptr);
5410 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5411 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
5412 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
5413 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5414 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5416 ocean_assert(sourcePaddingElements == 0u);
5417 ocean_assert(targetPaddingElements == 0u);
5421 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5422 const PixelType*
const sourcePixelData = (
const PixelType*)source;
5425 unsigned int leftOffsets[8];
5438 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5439 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5441 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5442 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5445 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5448 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5451 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5454 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5456 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5457 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5459 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5461 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5463 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5464 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5465 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5467 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5469 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5471 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
5473 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
5474 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
5476 for (
unsigned int x = 0; x < targetWidth; x += 8u)
5478 if (x + 8u > targetWidth)
5483 ocean_assert(x >= 8u && targetWidth > 8u);
5484 const unsigned int newX = targetWidth - 8u;
5486 ocean_assert(x > newX);
5487 targetPixelData -= x - newX;
5492 ocean_assert(!(x + 8u < targetWidth));
5498 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
5499 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
5502 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))));
5503 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
5505 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))));
5506 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
5510 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
5511 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
5514 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
5515 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
5522 uint8x8x2_t topLeftPixels;
5523 uint8x8x2_t topRightPixels;
5525 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
5526 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
5528 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
5529 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
5531 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
5532 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
5534 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
5535 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
5537 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
5538 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
5540 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
5541 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
5543 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
5544 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
5546 topLeftPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
5547 topRightPixels = vld2_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
5552 uint8x8x2_t bottomLeftPixels;
5553 uint8x8x2_t bottomRightPixels;
5555 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
5556 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
5558 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
5559 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
5561 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
5562 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
5564 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
5565 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
5567 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
5568 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
5570 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
5571 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
5573 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
5574 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
5576 bottomLeftPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
5577 bottomRightPixels = vld2_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
5585 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5586 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5589 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
5590 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
5591 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
5596 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
5597 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
5599 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
5600 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
5602 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5603 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5608 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
5609 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
5611 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
5612 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
5614 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5615 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5620 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
5621 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
5623 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
5624 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
5629 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
5630 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
5633 vst2_u8((uint8_t*)targetPixelData, result);
5635 targetPixelData += 8;
5641 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
5643 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
5645 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
5647 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
5648 ocean_assert(lastSourcePixelLeft < sourceWidth);
5649 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
5651 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
5653 const unsigned int factorRight = factorRight_fixed16 >> 9u;
5654 const unsigned int factorLeft = 128u - factorRight;
5656 for (
unsigned int c = 0u; c < 2u; ++c)
5658 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
5659 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
5667 #ifdef OCEAN_WE_KEEP_ALSO_THIS_SLOW_IMPLEMENTATION_SHOWING_A_SLIGHTLY_DIFFERENT_APPROACH
5670 inline 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)
5672 ocean_assert(source !=
nullptr && target !=
nullptr);
5673 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5674 ocean_assert(sourceHeight >= 0u && sourceHeight <= 65535u);
5675 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u)
5676 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5677 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5679 ocean_assert(sourcePaddingElements == 0u);
5680 ocean_assert(targetPaddingElements == 0u);
5682 typedef typename
DataType<uint8_t, 2u>::Type PixelType;
5684 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5685 const PixelType* const sourcePixelData = (const PixelType*)source;
5688 unsigned int leftOffsets[8];
5691 unsigned int topPixels[8];
5692 unsigned int bottomPixels[8];
5705 const
unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5706 const
unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5708 const
int targetOffsetX_fixed16 = (
int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5709 const
int targetOffsetY_fixed16 = (
int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5712 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5715 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5718 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5721 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5723 const
unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5724 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5726 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5728 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5730 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5731 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5732 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5734 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5736 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5738 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
5740 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
5741 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
5743 for (
unsigned int x = 0; x < targetWidth; x += 8u)
5745 if (x + 8u > targetWidth)
5750 ocean_assert(x >= 8u && targetWidth > 8u);
5751 const unsigned int newX = targetWidth - 8u;
5753 ocean_assert(x > newX);
5754 targetPixelData -= x - newX;
5759 ocean_assert(!(x + 8u < targetWidth));
5765 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
5766 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
5769 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))));
5770 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
5772 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))));
5773 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
5777 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
5778 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
5781 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
5782 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
5792 for (
unsigned int n = 0u; n < 8u; ++n)
5794 topPixels[n] = *(
unsigned int*)(sourceTopRowPixelData + leftOffsets[n]);
5797 const uint16x8_t m128_topPixels_0123 = vreinterpretq_u16_u32(vld1q_u32(topPixels + 0));
5798 const uint16x8_t m128_topPixels_4567 = vreinterpretq_u16_u32(vld1q_u32(topPixels + 4));
5800 for (
unsigned int n = 0u; n < 8u; ++n)
5802 bottomPixels[n] = *(
unsigned int*)(sourceBottomRowPixelData + leftOffsets[n]);
5805 const uint16x8_t m128_bottomPixels_0123 = vreinterpretq_u16_u32(vld1q_u32(bottomPixels + 0));
5806 const uint16x8_t m128_bottomPixels_4567 = vreinterpretq_u16_u32(vld1q_u32(bottomPixels + 4));
5813 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5814 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
5817 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
5818 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
5823 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
5830 const uint16x8x2_t m2_128_topPixelsLeftRight = vuzpq_u16(m128_topPixels_0123, m128_topPixels_4567);
5836 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])));
5837 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])));
5839 const uint8x8_t& m64_topPixelsLeft_channel_0 = m2_64_topPixelsLeft_channels_01.val[0];
5840 const uint8x8_t& m64_topPixelsLeft_channel_1 = m2_64_topPixelsLeft_channels_01.val[1];
5842 const uint8x8_t& m64_topPixelsRight_channel_0 = m2_64_topPixelsRight_channels_01.val[0];
5843 const uint8x8_t& m64_topPixelsRight_channel_1 = m2_64_topPixelsRight_channels_01.val[1];
5847 uint16x8_t m128_muliplication_channel_0 = vmull_u8(m64_topPixelsLeft_channel_0, m64_u_factorsLeft);
5848 uint16x8_t m128_muliplication_channel_1 = vmull_u8(m64_topPixelsLeft_channel_1, m64_u_factorsLeft);
5850 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_topPixelsRight_channel_0, m64_u_factorsRight);
5851 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_topPixelsRight_channel_1, m64_u_factorsRight);
5853 const uint8x8_t m64_topRow_channel_0 = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5854 const uint8x8_t m64_topRow_channel_1 = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5858 const uint16x8x2_t m2_128_bottomPixelsLeftRight = vuzpq_u16(m128_bottomPixels_0123, m128_bottomPixels_4567);
5860 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])));
5861 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])));
5863 const uint8x8_t& m64_bottomPixelsLeft_channel_0 = m2_64_bottomPixelsLeft_channels_01.val[0];
5864 const uint8x8_t& m64_bottomPixelsLeft_channel_1 = m2_64_bottomPixelsLeft_channels_01.val[1];
5866 const uint8x8_t& m64_bottomPixelsRight_channel_0 = m2_64_bottomPixelsRight_channels_01.val[0];
5867 const uint8x8_t& m64_bottomPixelsRight_channel_1 = m2_64_bottomPixelsRight_channels_01.val[1];
5871 m128_muliplication_channel_0 = vmull_u8(m64_bottomPixelsLeft_channel_0, m64_u_factorsLeft);
5872 m128_muliplication_channel_1 = vmull_u8(m64_bottomPixelsLeft_channel_1, m64_u_factorsLeft);
5874 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_bottomPixelsRight_channel_0, m64_u_factorsRight);
5875 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_bottomPixelsRight_channel_1, m64_u_factorsRight);
5877 const uint8x8_t m64_bottomRow_channel_0 = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5878 const uint8x8_t m64_bottomRow_channel_1 = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5882 m128_muliplication_channel_0 = vmull_u8(m64_topRow_channel_0, m64_u_factorsTop);
5883 m128_muliplication_channel_1 = vmull_u8(m64_topRow_channel_1, m64_u_factorsTop);
5885 m128_muliplication_channel_0 = vmlal_u8(m128_muliplication_channel_0, m64_bottomRow_channel_0, m64_u_factorsBottom);
5886 m128_muliplication_channel_1 = vmlal_u8(m128_muliplication_channel_1, m64_bottomRow_channel_1, m64_u_factorsBottom);
5890 uint8x8x2_t m2_64_result;
5891 m2_64_result.val[0] = vrshrn_n_u16(m128_muliplication_channel_0, 7);
5892 m2_64_result.val[1] = vrshrn_n_u16(m128_muliplication_channel_1, 7);
5895 vst2_u8((uint8_t*)targetPixelData, m2_64_result);
5897 targetPixelData += 8;
5903 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
5905 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
5907 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
5909 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
5910 ocean_assert(lastSourcePixelLeft < sourceWidth);
5911 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
5913 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
5915 const unsigned int factorRight = factorRight_fixed16 >> 9u;
5916 const unsigned int factorLeft = 128u - factorRight;
5918 for (
unsigned int c = 0u; c < 2u; ++c)
5920 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
5921 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
5929 #ifdef OCEAN_WE_KEEP_THIS_IMPLEMENTATION_AS_WE_NEED_THIS_TO_FOR_A_NEW_NEON_IMPLEMENTATION
5932 inline 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)
5934 ocean_assert(source !=
nullptr && target !=
nullptr);
5935 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
5936 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
5937 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
5938 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
5939 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
5941 ocean_assert(sourcePaddingElements == 0u);
5942 ocean_assert(targetPaddingElements == 0u);
5944 typedef typename DataType<uint8_t, 3u>::Type PixelType;
5946 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
5947 const PixelType*
const sourcePixelData = (
const PixelType*)source;
5950 unsigned int leftOffsets[8];
5963 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
5964 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
5966 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
5967 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
5970 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
5973 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
5976 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
5979 const int32x4_t m128_s_zero = vdupq_n_s32(0);
5981 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
5982 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
5984 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
5986 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
5988 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
5989 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
5990 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
5992 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
5994 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
5996 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
5998 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
5999 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6001 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6003 if (x + 8u > targetWidth)
6008 ocean_assert(x >= 8u && targetWidth > 8u);
6009 const unsigned int newX = targetWidth - 8u;
6011 ocean_assert(x > newX);
6012 targetPixelData -= x - newX;
6017 ocean_assert(!(x + 8u < targetWidth));
6023 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6024 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6027 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))));
6028 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6030 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))));
6031 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6035 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6036 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6039 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6040 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6047 uint8x8x3_t topLeftPixels;
6048 uint8x8x3_t topRightPixels;
6050 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
6051 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
6053 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
6054 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
6056 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
6057 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
6059 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
6060 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
6062 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
6063 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
6065 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
6066 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
6068 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
6069 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
6071 topLeftPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
6072 topRightPixels = vld3_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
6077 uint8x8x3_t bottomLeftPixels;
6078 uint8x8x3_t bottomRightPixels;
6080 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
6081 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
6083 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
6084 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
6086 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
6087 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
6089 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
6090 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
6092 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
6093 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
6095 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
6096 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
6098 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
6099 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
6101 bottomLeftPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
6102 bottomRightPixels = vld3_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
6110 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6111 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6114 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6115 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6116 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6121 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
6122 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
6123 uint16x8_t m128_muliplicationChannel_2 = vmull_u8(topLeftPixels.val[2], m64_u_factorsLeft);
6125 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
6126 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
6127 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, topRightPixels.val[2], m64_u_factorsRight);
6129 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6130 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6131 uint8x8_t m64_topRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6136 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
6137 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
6138 m128_muliplicationChannel_2 = vmull_u8(bottomLeftPixels.val[2], m64_u_factorsLeft);
6140 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
6141 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
6142 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, bottomRightPixels.val[2], m64_u_factorsRight);
6144 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6145 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6146 uint8x8_t m64_bottomRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6151 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
6152 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
6153 m128_muliplicationChannel_2 = vmull_u8(m64_topRowChannel_2, m64_u_factorsTop);
6155 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
6156 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
6157 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, m64_bottomRowChannel_2, m64_u_factorsBottom);
6162 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6163 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6164 result.val[2] = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6167 vst3_u8((uint8_t*)targetPixelData, result);
6169 targetPixelData += 8;
6175 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6177 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6179 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6181 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6182 ocean_assert(lastSourcePixelLeft < sourceWidth);
6183 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6185 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6187 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6188 const unsigned int factorLeft = 128u - factorRight;
6190 for (
unsigned int c = 0u; c < 3u; ++c)
6192 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * (128u - factorBottom)
6193 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6201 #ifdef OCEAN_WE_KEEP_ALSO_THIS_SLOW_IMPLEMENTATION_SHOWING_A_MORE_GENERIC_APPROACH
6206 inline 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)
6208 ocean_assert(source !=
nullptr && target !=
nullptr);
6209 ocean_assert(sourceWidth >= 2u && sourceWidth <= 65535u);
6210 ocean_assert(sourceHeight >= 1u && sourceHeight <= 65535u);
6211 ocean_assert(targetWidth >= 8u && targetWidth <= 65535u);
6212 ocean_assert(targetHeight >= 1u && targetHeight <= 65535u);
6213 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6215 ocean_assert(sourcePaddingElements == 0u);
6216 ocean_assert(targetPaddingElements == 0u);
6218 typedef typename DataType<uint8_t, 4u>::Type PixelType;
6220 PixelType* targetPixelData = (PixelType*)target + firstTargetRow * targetWidth;
6221 const PixelType*
const sourcePixelData = (
const PixelType*)source;
6224 unsigned int leftOffsets[8];
6227 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6240 const unsigned int sourceX_T_targetX_fixed16 = (
unsigned int)(
double(0x10000u) * sourceX_s_targetX + 0.5);
6241 const unsigned int sourceY_T_targetY_fixed16 = (
unsigned int)(
double(0x10000u) * sourceY_s_targetY + 0.5);
6243 const int targetOffsetX_fixed16 = (int)(
double(0x10000u) * ((sourceX_s_targetX * 0.5) - 0.5) + 0.5);
6244 const int targetOffsetY_fixed16 = (int)(
double(0x10000u) * ((sourceY_s_targetY * 0.5) - 0.5) + 0.5);
6247 const uint32x4_t m128_u_sourceX_T_targetX_fixed16 = vdupq_n_u32(sourceX_T_targetX_fixed16);
6250 const int32x4_t m128_s_targetOffsetX_fixed16 = vdupq_n_s32(targetOffsetX_fixed16);
6253 const uint32x4_t m128_u_sourceWidth_2 = vdupq_n_u32(sourceWidth - 2u);
6256 const int32x4_t m128_s_zero = vdupq_n_s32(0);
6258 const unsigned int u_0123[4] = {0u, 1u, 2u, 3u};
6259 const uint32x4_t m128_u_0123 = vld1q_u32(u_0123);
6261 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6263 const unsigned int sourceY_fixed16 = minmax<int>(0, targetOffsetY_fixed16 +
int(sourceY_T_targetY_fixed16 * y), (sourceHeight - 1u) << 16u);
6265 const unsigned int sourceRowTop = sourceY_fixed16 >> 16u;
6266 const unsigned int factorBottom_fixed16 = sourceY_fixed16 & 0x0000FFFFu;
6267 const unsigned int factorBottom = factorBottom_fixed16 >> 9u;
6269 const uint8x8_t m64_u_factorsBottom = vdup_n_u8(factorBottom);
6271 const uint8x8_t m64_u_factorsTop = vdup_n_u8(128u - factorBottom);
6273 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6275 const PixelType*
const sourceTopRowPixelData = sourcePixelData + sourceRowTop * sourceWidth;
6276 const PixelType*
const sourceBottomRowPixelData = sourcePixelData + sourceRowBottom * sourceWidth;
6278 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6280 if (x + 8u > targetWidth)
6285 ocean_assert(x >= 8u && targetWidth > 8u);
6286 const unsigned int newX = targetWidth - 8u;
6288 ocean_assert(x > newX);
6289 targetPixelData -= x - newX;
6294 ocean_assert(!(x + 8u < targetWidth));
6300 const uint32x4_t m128_u_x_0123 = vaddq_u32(vdupq_n_u32(x), m128_u_0123);
6301 const uint32x4_t m128_u_x_4567 = vaddq_u32(vdupq_n_u32(x + 4u), m128_u_0123);
6304 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))));
6305 const uint32x4_t m128_u_sourceX_0123_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_0123_fixed16);
6307 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))));
6308 const uint32x4_t m128_u_sourceX_4567_fixed16 = vreinterpretq_u32_s32(m128_s_sourceX_4567_fixed16);
6312 const uint32x4_t m128_u_left_0123 = vminq_u32(vshrq_n_u32(m128_u_sourceX_0123_fixed16, 16), m128_u_sourceWidth_2);
6313 const uint32x4_t m128_u_left_4567 = vminq_u32(vshrq_n_u32(m128_u_sourceX_4567_fixed16, 16), m128_u_sourceWidth_2);
6316 vst1q_u32(leftOffsets + 0, m128_u_left_0123);
6317 vst1q_u32(leftOffsets + 4, m128_u_left_4567);
6324 uint8x8x4_t topLeftPixels;
6325 uint8x8x4_t topRightPixels;
6327 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 0), topLeftPixels, 0);
6328 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[0u] + 1), topRightPixels, 0);
6330 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 0), topLeftPixels, 1);
6331 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[1u] + 1), topRightPixels, 1);
6333 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 0), topLeftPixels, 2);
6334 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[2u] + 1), topRightPixels, 2);
6336 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 0), topLeftPixels, 3);
6337 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[3u] + 1), topRightPixels, 3);
6339 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 0), topLeftPixels, 4);
6340 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[4u] + 1), topRightPixels, 4);
6342 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 0), topLeftPixels, 5);
6343 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[5u] + 1), topRightPixels, 5);
6345 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 0), topLeftPixels, 6);
6346 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[6u] + 1), topRightPixels, 6);
6348 topLeftPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 0), topLeftPixels, 7);
6349 topRightPixels = vld4_lane_u8((uint8_t*)(sourceTopRowPixelData + leftOffsets[7u] + 1), topRightPixels, 7);
6354 uint8x8x4_t bottomLeftPixels;
6355 uint8x8x4_t bottomRightPixels;
6357 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 0), bottomLeftPixels, 0);
6358 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[0u] + 1), bottomRightPixels, 0);
6360 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 0), bottomLeftPixels, 1);
6361 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[1u] + 1), bottomRightPixels, 1);
6363 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 0), bottomLeftPixels, 2);
6364 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[2u] + 1), bottomRightPixels, 2);
6366 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 0), bottomLeftPixels, 3);
6367 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[3u] + 1), bottomRightPixels, 3);
6369 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 0), bottomLeftPixels, 4);
6370 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[4u] + 1), bottomRightPixels, 4);
6372 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 0), bottomLeftPixels, 5);
6373 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[5u] + 1), bottomRightPixels, 5);
6375 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 0), bottomLeftPixels, 6);
6376 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[6u] + 1), bottomRightPixels, 6);
6378 bottomLeftPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 0), bottomLeftPixels, 7);
6379 bottomRightPixels = vld4_lane_u8((uint8_t*)(sourceBottomRowPixelData + leftOffsets[7u] + 1), bottomRightPixels, 7);
6387 const uint16x4_t m64_u_factorsRight_0123 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_0123_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6388 const uint16x4_t m64_u_factorsRight_4567 = vrshrn_n_u32(vandq_u32(m128_u_sourceX_4567_fixed16, vdupq_n_u32(0x0000FFFFu)), 9);
6391 const uint16x8_t m128_u_factorsRight = vcombine_u16(m64_u_factorsRight_0123, m64_u_factorsRight_4567);
6392 const uint8x8_t m64_u_factorsRight = vqmovn_u16(m128_u_factorsRight);
6393 const uint8x8_t m64_u_factorsLeft = vsub_u8(vdup_n_u8(128u), m64_u_factorsRight);
6398 uint16x8_t m128_muliplicationChannel_0 = vmull_u8(topLeftPixels.val[0], m64_u_factorsLeft);
6399 uint16x8_t m128_muliplicationChannel_1 = vmull_u8(topLeftPixels.val[1], m64_u_factorsLeft);
6400 uint16x8_t m128_muliplicationChannel_2 = vmull_u8(topLeftPixels.val[2], m64_u_factorsLeft);
6401 uint16x8_t m128_muliplicationChannel_3 = vmull_u8(topLeftPixels.val[3], m64_u_factorsLeft);
6403 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, topRightPixels.val[0], m64_u_factorsRight);
6404 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, topRightPixels.val[1], m64_u_factorsRight);
6405 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, topRightPixels.val[2], m64_u_factorsRight);
6406 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, topRightPixels.val[3], m64_u_factorsRight);
6408 uint8x8_t m64_topRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6409 uint8x8_t m64_topRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6410 uint8x8_t m64_topRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6411 uint8x8_t m64_topRowChannel_3 = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6416 m128_muliplicationChannel_0 = vmull_u8(bottomLeftPixels.val[0], m64_u_factorsLeft);
6417 m128_muliplicationChannel_1 = vmull_u8(bottomLeftPixels.val[1], m64_u_factorsLeft);
6418 m128_muliplicationChannel_2 = vmull_u8(bottomLeftPixels.val[2], m64_u_factorsLeft);
6419 m128_muliplicationChannel_3 = vmull_u8(bottomLeftPixels.val[3], m64_u_factorsLeft);
6421 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, bottomRightPixels.val[0], m64_u_factorsRight);
6422 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, bottomRightPixels.val[1], m64_u_factorsRight);
6423 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, bottomRightPixels.val[2], m64_u_factorsRight);
6424 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, bottomRightPixels.val[3], m64_u_factorsRight);
6426 uint8x8_t m64_bottomRowChannel_0 = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6427 uint8x8_t m64_bottomRowChannel_1 = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6428 uint8x8_t m64_bottomRowChannel_2 = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6429 uint8x8_t m64_bottomRowChannel_3 = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6434 m128_muliplicationChannel_0 = vmull_u8(m64_topRowChannel_0, m64_u_factorsTop);
6435 m128_muliplicationChannel_1 = vmull_u8(m64_topRowChannel_1, m64_u_factorsTop);
6436 m128_muliplicationChannel_2 = vmull_u8(m64_topRowChannel_2, m64_u_factorsTop);
6437 m128_muliplicationChannel_3 = vmull_u8(m64_topRowChannel_3, m64_u_factorsTop);
6439 m128_muliplicationChannel_0 = vmlal_u8(m128_muliplicationChannel_0, m64_bottomRowChannel_0, m64_u_factorsBottom);
6440 m128_muliplicationChannel_1 = vmlal_u8(m128_muliplicationChannel_1, m64_bottomRowChannel_1, m64_u_factorsBottom);
6441 m128_muliplicationChannel_2 = vmlal_u8(m128_muliplicationChannel_2, m64_bottomRowChannel_2, m64_u_factorsBottom);
6442 m128_muliplicationChannel_3 = vmlal_u8(m128_muliplicationChannel_3, m64_bottomRowChannel_3, m64_u_factorsBottom);
6447 result.val[0] = vrshrn_n_u16(m128_muliplicationChannel_0, 7);
6448 result.val[1] = vrshrn_n_u16(m128_muliplicationChannel_1, 7);
6449 result.val[2] = vrshrn_n_u16(m128_muliplicationChannel_2, 7);
6450 result.val[3] = vrshrn_n_u16(m128_muliplicationChannel_3, 7);
6453 vst4_u8((uint8_t*)targetPixelData, result);
6455 targetPixelData += 8;
6461 const unsigned int firstInvalidTargetX = (((sourceWidth - 1u) << 16u) - targetOffsetX_fixed16) / sourceX_T_targetX_fixed16;
6463 for (
unsigned int x = firstInvalidTargetX; x < targetWidth; ++x)
6465 const unsigned int lastSourcePixelPosition_fixed16 = minmax<int>(0, targetOffsetX_fixed16 +
int(sourceX_T_targetX_fixed16 * x), (sourceWidth - 1u) << 16u);
6467 const unsigned int lastSourcePixelLeft = lastSourcePixelPosition_fixed16 >> 16u;
6468 ocean_assert(lastSourcePixelLeft < sourceWidth);
6469 const unsigned int lastSourcePixelRight = min(lastSourcePixelLeft + 1u, sourceWidth - 1u);
6471 const unsigned int factorRight_fixed16 = lastSourcePixelPosition_fixed16 & 0x0000FFFFu;
6473 const unsigned int factorRight = factorRight_fixed16 >> 9u;
6474 const unsigned int factorLeft = 128u - factorRight;
6476 for (
unsigned int c = 0u; c < 4u; ++c)
6478 ((uint8_t*)(targetPixelData - (targetWidth - x)))[c] = ((((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceTopRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorTop
6479 + (((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelLeft))[c] * factorLeft + ((
const uint8_t*)(sourceBottomRowPixelData + lastSourcePixelRight))[c] * factorRight) * factorBottom + 8192u) >> 14u;
6490 inline void FrameInterpolatorBilinear::interpolateRowVerticalNEON<float>(
const float* sourceRowTop,
const float* sourceRowBottom,
float* targetRow,
const unsigned int elements,
const float factorBottom)
6492 ocean_assert(sourceRowTop !=
nullptr);
6493 ocean_assert(sourceRowBottom !=
nullptr);
6494 ocean_assert(targetRow !=
nullptr);
6495 ocean_assert(elements >= 16u);
6496 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
6499 const float32x4_t constant_1_f_32x4 = vdupq_n_f32(1.0f);
6501 const float32x4_t factorsBottom_f_32x4 = vdupq_n_f32(factorBottom);
6502 const float32x4_t factorsTop_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsBottom_f_32x4);
6504 for (
unsigned int n = 0u; n < elements; n += 16u)
6506 if (n + 16u > elements)
6511 ocean_assert(n >= 16u && elements > 16u);
6512 const unsigned int offset = n - (elements - 16u);
6513 ocean_assert(offset < 16u);
6515 sourceRowTop -= offset;
6516 sourceRowBottom -= offset;
6517 targetRow -= offset;
6520 ocean_assert(!(n + 16u < elements));
6524 const float32x4_t top_03_32x4 = vld1q_f32(sourceRowTop + 0);
6525 const float32x4_t top_47_32x4 = vld1q_f32(sourceRowTop + 4);
6526 const float32x4_t top_8B_32x4 = vld1q_f32(sourceRowTop + 8);
6527 const float32x4_t top_CF_32x4 = vld1q_f32(sourceRowTop + 12);
6529 const float32x4_t bottom_03_32x4 = vld1q_f32(sourceRowBottom + 0);
6530 const float32x4_t bottom_47_32x4 = vld1q_f32(sourceRowBottom + 4);
6531 const float32x4_t bottom_8B_32x4 = vld1q_f32(sourceRowBottom + 8);
6532 const float32x4_t bottom_CF_32x4 = vld1q_f32(sourceRowBottom + 12);
6535 float32x4_t interpolatedRow_03_32x4 = vmulq_f32(top_03_32x4, factorsTop_f_32x4);
6536 float32x4_t interpolatedRow_47_32x4 = vmulq_f32(top_47_32x4, factorsTop_f_32x4);
6537 float32x4_t interpolatedRow_8B_32x4 = vmulq_f32(top_8B_32x4, factorsTop_f_32x4);
6538 float32x4_t interpolatedRow_CF_32x4 = vmulq_f32(top_CF_32x4, factorsTop_f_32x4);
6540 interpolatedRow_03_32x4 = vmlaq_f32(interpolatedRow_03_32x4, bottom_03_32x4, factorsBottom_f_32x4);
6541 interpolatedRow_47_32x4 = vmlaq_f32(interpolatedRow_47_32x4, bottom_47_32x4, factorsBottom_f_32x4);
6542 interpolatedRow_8B_32x4 = vmlaq_f32(interpolatedRow_8B_32x4, bottom_8B_32x4, factorsBottom_f_32x4);
6543 interpolatedRow_CF_32x4 = vmlaq_f32(interpolatedRow_CF_32x4, bottom_CF_32x4, factorsBottom_f_32x4);
6546 vst1q_f32(targetRow + 0, interpolatedRow_03_32x4);
6547 vst1q_f32(targetRow + 4, interpolatedRow_47_32x4);
6548 vst1q_f32(targetRow + 8, interpolatedRow_8B_32x4);
6549 vst1q_f32(targetRow + 12, interpolatedRow_CF_32x4);
6552 sourceRowBottom += 16;
6558 inline 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)
6560 ocean_assert(extendedSourceRow !=
nullptr);
6561 ocean_assert(targetRow !=
nullptr);
6562 ocean_assert(targetWidth >= 8u);
6563 ocean_assert(interpolationLocations !=
nullptr);
6564 ocean_assert(interpolationFactorsRight !=
nullptr);
6566 ocean_assert(channels == 1u);
6569 const float32x4_t constant_1_f_32x4 = vdupq_n_f32(1.0f);
6571 for (
unsigned int x = 0; x < targetWidth; x += 8u)
6573 if (x + 8u > targetWidth)
6578 ocean_assert(x >= 8u && targetWidth > 8u);
6579 const unsigned int newX = targetWidth - 8u;
6581 ocean_assert(x > newX);
6582 const unsigned int offset = x - newX;
6584 targetRow -= offset;
6585 interpolationLocations -= offset;
6586 interpolationFactorsRight -= offset;
6591 ocean_assert(!(x + 8u < targetWidth));
6596 const float32x2_t pixel_0_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[0]);
6597 const float32x2_t pixel_1_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[1]);
6598 const float32x4_t pixel_01_f_32x4 = vcombine_f32(pixel_0_f_32x2, pixel_1_f_32x2);
6600 const float32x2_t pixel_2_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[2]);
6601 const float32x2_t pixel_3_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[3]);
6602 const float32x4_t pixel_23_f_32x4 = vcombine_f32(pixel_2_f_32x2, pixel_3_f_32x2);
6604 const float32x2_t pixel_4_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[4]);
6605 const float32x2_t pixel_5_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[5]);
6606 const float32x4_t pixel_45_f_32x4 = vcombine_f32(pixel_4_f_32x2, pixel_5_f_32x2);
6608 const float32x2_t pixel_6_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[6]);
6609 const float32x2_t pixel_7_f_32x2 = vld1_f32(extendedSourceRow + interpolationLocations[7]);
6610 const float32x4_t pixel_67_f_32x4 = vcombine_f32(pixel_6_f_32x2, pixel_7_f_32x2);
6612 const float32x4_t factorsRight_0123_f_32x4 = vld1q_f32(interpolationFactorsRight + 0);
6613 const float32x4_t factorsLeft_0123_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsRight_0123_f_32x4);
6614 const float32x4x2_t factorsLeftRight_0123_f_32x4_2 = vzipq_f32(factorsLeft_0123_f_32x4, factorsRight_0123_f_32x4);
6616 const float32x4_t factorsRight_4567_f_32x4 = vld1q_f32(interpolationFactorsRight + 4);
6617 const float32x4_t factorsLeft_4567_f_32x4 = vsubq_f32(constant_1_f_32x4, factorsRight_4567_f_32x4);
6618 const float32x4x2_t factorsLeftRight_4567_f_32x4_2 = vzipq_f32(factorsLeft_4567_f_32x4, factorsRight_4567_f_32x4);
6620 const float32x4_t multiplied_01_f_32x4 = vmulq_f32(pixel_01_f_32x4, factorsLeftRight_0123_f_32x4_2.val[0]);
6621 const float32x4_t multiplied_23_f_32x4 = vmulq_f32(pixel_23_f_32x4, factorsLeftRight_0123_f_32x4_2.val[1]);
6623 const float32x4_t multiplied_45_f_32x4 = vmulq_f32(pixel_45_f_32x4, factorsLeftRight_4567_f_32x4_2.val[0]);
6624 const float32x4_t multiplied_67_f_32x4 = vmulq_f32(pixel_67_f_32x4, factorsLeftRight_4567_f_32x4_2.val[1]);
6626 const float32x2_t result_01_f_32x2 = vpadd_f32(vget_low_f32(multiplied_01_f_32x4), vget_high_f32(multiplied_01_f_32x4));
6627 const float32x2_t result_23_f_32x2 = vpadd_f32(vget_low_f32(multiplied_23_f_32x4), vget_high_f32(multiplied_23_f_32x4));
6629 const float32x2_t result_45_f_32x2 = vpadd_f32(vget_low_f32(multiplied_45_f_32x4), vget_high_f32(multiplied_45_f_32x4));
6630 const float32x2_t result_67_f_32x2 = vpadd_f32(vget_low_f32(multiplied_67_f_32x4), vget_high_f32(multiplied_67_f_32x4));
6632 const float32x4_t result_0123_f_32x4 = vcombine_f32(result_01_f_32x2, result_23_f_32x2);
6633 const float32x4_t result_4567_f_32x4 = vcombine_f32(result_45_f_32x2, result_67_f_32x2);
6635 vst1q_f32(targetRow + 0, result_0123_f_32x4);
6636 vst1q_f32(targetRow + 4, result_4567_f_32x4);
6639 interpolationLocations += 8;
6640 interpolationFactorsRight += 8;
6645 inline 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)
6647 ocean_assert(source !=
nullptr && target !=
nullptr);
6648 ocean_assert(sourceWidth >= 1u && sourceHeight >= 1u);
6649 ocean_assert(targetWidth >= 1u && targetHeight >= 1u);
6650 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6652 ocean_assert(sourceWidth != targetWidth || sourceHeight != targetHeight);
6654 const unsigned int sourceStrideElements = sourceWidth * 1u + sourcePaddingElements;
6655 const unsigned int targetStrideElements = targetWidth * 1u + targetPaddingElements;
6657 typedef void (*InterpolateRowVerticalFunction)(
const float*,
const float*,
float*,
const unsigned int,
const float);
6658 typedef void (*InterpolateRowHorizontalFunction)(
const float*,
float*,
const unsigned int,
const unsigned int,
const unsigned int*,
const float*);
6660 InterpolateRowVerticalFunction interpolateRowVerticalFunction = interpolateRowVertical<float>;
6661 InterpolateRowHorizontalFunction interpolateRowHorizontalFunction = interpolateRowHorizontal<float, 1u>;
6663 if (sourceWidth * 1u >= 16u)
6665 interpolateRowVerticalFunction = interpolateRowVerticalNEON<float>;
6668 if (targetWidth >= 8u)
6670 interpolateRowHorizontalFunction = interpolateRowHorizontalNEON<float, 1u>;
6673 target += targetStrideElements * firstTargetRow;
6675 const float sourceX_T_targetX = float(sourceX_s_targetX);
6676 const float sourceY_T_targetY = float(sourceY_s_targetY);
6680 Memory memoryIntermediateExtendedRow;
6681 Memory memoryHorizontalInterpolationLocations;
6682 Memory memoryHorizontalInterpolationFactorsRight;
6684 if (sourceWidth != targetWidth)
6688 memoryIntermediateExtendedRow = Memory::create<float>(sourceWidth + 1u);
6690 memoryHorizontalInterpolationLocations = Memory::create<unsigned int>(targetWidth);
6692 memoryHorizontalInterpolationFactorsRight = Memory::create<float>(targetWidth);
6695 if (memoryHorizontalInterpolationLocations)
6697 ocean_assert(memoryHorizontalInterpolationFactorsRight);
6699 if (targetWidth >= 4u)
6701 const float32x4_t sourceX_T_targetX_f_32x4 = vdupq_n_f32(sourceX_T_targetX);
6702 const float32x4_t targetOffsetX_f_32x4 = vdupq_n_f32(sourceX_T_targetX * 0.5f - 0.5f);
6705 const float32x4_t constant_0_f_32x4 = vdupq_n_f32(0);
6708 const float32x4_t constant_4_f_32x4 = vdupq_n_f32(4.0f);
6711 const uint32x4_t sourceWidth_1_u_32x4 = vdupq_n_u32(sourceWidth - 1u);
6714 const float f_0123[4] = {0.0f, 1.0f, 2.0f, 3.0f};
6715 float32x4_t x_0123_f_32x4 = vld1q_f32(f_0123);
6719 for (
unsigned int x = 0u; x < targetWidth; x += 4u)
6721 if (x + 4u > targetWidth)
6726 ocean_assert(x >= 4u && targetWidth > 4u);
6727 const unsigned int newX = targetWidth - 4u;
6729 ocean_assert(x > newX);
6730 const unsigned int offset = x - newX;
6734 x_0123_f_32x4 = vsubq_f32(x_0123_f_32x4, vdupq_n_f32(
float(offset)));
6737 ocean_assert(!(x + 4u < targetWidth));
6741 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)));
6745 uint32x4_t left_0123_u_32x4 = vminq_u32(vcvtq_u32_f32(sourceX_0123_f_32x4), sourceWidth_1_u_32x4);
6748 vst1q_u32(memoryHorizontalInterpolationLocations.
data<
unsigned int>() + x, left_0123_u_32x4);
6751 const float32x4_t factorsRight_f_32x4 = vsubq_f32(sourceX_0123_f_32x4, vcvtq_f32_u32(left_0123_u_32x4));
6753 vst1q_f32(memoryHorizontalInterpolationFactorsRight.
data<
float>() + x, factorsRight_f_32x4);
6756 x_0123_f_32x4 = vaddq_f32(x_0123_f_32x4, constant_4_f_32x4);
6761 const float targetOffsetX = sourceX_T_targetX * 0.5f - 0.5f;
6765 for (
unsigned int x = 0u; x < targetWidth; ++x)
6767 const float sourceX = max(0.0f, targetOffsetX +
float(x) * sourceX_T_targetX);
6769 const unsigned int left = min((
unsigned int)sourceX, sourceWidth - 1u);
6771 memoryHorizontalInterpolationLocations.
data<
unsigned int>()[x] = left;
6773 const float factorRight = sourceX - float(left);
6774 ocean_assert(factorRight >= 0.0f && factorRight <= 1.0f);
6776 memoryHorizontalInterpolationFactorsRight.
data<
float>()[x] = factorRight;
6781 const float targetOffsetY = sourceY_T_targetY * 0.5f - 0.5f;
6783 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6785 const float sourceY = minmax<float>(0.0f, targetOffsetY + sourceY_T_targetY *
float(y),
float(sourceHeight) - 1.0f);
6787 const unsigned int sourceRowTop = (
unsigned int)sourceY;
6788 const float factorBottom = sourceY - float(sourceRowTop);
6789 ocean_assert(factorBottom >= 0.0f && factorBottom <= 1.0f);
6791 const unsigned int sourceRowBottom = min(sourceRowTop + 1u, sourceHeight - 1u);
6793 const float*
const sourceTopRow = source + sourceStrideElements * sourceRowTop;
6794 const float*
const sourceBottomRow = source + sourceStrideElements * sourceRowBottom;
6796 float* targetRow =
nullptr;
6798 if (sourceHeight == targetHeight)
6800 ocean_assert(sourceWidth != targetWidth);
6801 ocean_assert(memoryIntermediateExtendedRow);
6804 memcpy(memoryIntermediateExtendedRow.
data<
float>(), sourceTopRow, sourceWidth *
sizeof(
float));
6809 targetRow = memoryIntermediateExtendedRow.
isNull() ? target : memoryIntermediateExtendedRow.
data<
float>();
6811 ocean_assert(targetRow !=
nullptr);
6812 ocean_assert(interpolateRowVerticalFunction !=
nullptr);
6813 interpolateRowVerticalFunction(sourceTopRow, sourceBottomRow, targetRow, sourceWidth * 1u, factorBottom);
6816 if (memoryIntermediateExtendedRow)
6820 memoryIntermediateExtendedRow.
data<
float>()[sourceWidth] = memoryIntermediateExtendedRow.
data<
float>()[sourceWidth - 1u];
6822 interpolateRowHorizontalFunction(memoryIntermediateExtendedRow.
data<
float>(), target, targetWidth, 1u, memoryHorizontalInterpolationLocations.
data<
unsigned int>(), memoryHorizontalInterpolationFactorsRight.
data<
float>());
6825 target += targetStrideElements;
6831 template <
typename T,
typename TScale,
unsigned int tChannels>
6832 void 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)
6834 static_assert((std::is_same<float, TScale>::value || std::is_same<double, TScale>::value),
"Invalid TScale type");
6836 ocean_assert(source !=
nullptr && target !=
nullptr);
6837 ocean_assert(sourceWidth != 0u && sourceHeight != 0u);
6838 ocean_assert_and_suppress_unused(targetWidth >= 1u && targetHeight >= 1u, targetHeight);
6839 ocean_assert(sourceX_s_targetX > 0.0 && sourceY_s_targetY > 0.0);
6841 const unsigned int sourceStrideElements = sourceWidth * tChannels + sourcePaddingElements;
6842 const unsigned int targetStrideElements = targetWidth * tChannels + targetPaddingElements;
6844 const TScale sourceX_T_targetX = TScale(sourceX_s_targetX);
6845 const TScale sourceY_T_targetY = TScale(sourceY_s_targetY);
6893 const TScale sourceX_T_targetXOffset = sourceX_T_targetX * TScale(0.5) - TScale(0.5);
6894 const TScale sourceY_T_targetYOffset = sourceY_T_targetY * TScale(0.5) - TScale(0.5);
6896 const TScale sourceWidth_1 = TScale(sourceWidth - 1u);
6897 const TScale sourceHeight_1 = TScale(sourceHeight - 1u);
6899 target += targetStrideElements * firstTargetRow;
6901 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6903 const TScale sy =
minmax(TScale(0), sourceY_T_targetYOffset + sourceY_T_targetY * TScale(y), sourceHeight_1);
6904 ocean_assert(sy >= TScale(0) && sy < TScale(sourceHeight));
6906 const unsigned int sTop = (
unsigned int)sy;
6907 ocean_assert(sy >= TScale(sTop));
6909 const TScale factorBottom = sy - TScale(sTop);
6910 ocean_assert(factorBottom >= TScale(0) && factorBottom <= TScale(1));
6912 const TScale factorTop = TScale(1) - factorBottom;
6913 ocean_assert(factorTop >= TScale(0) && factorTop <= TScale(1));
6915 const T*
const sourceTop = source + sTop * sourceStrideElements;
6916 const T*
const sourceBottom = (sTop + 1u < sourceHeight) ? sourceTop + sourceStrideElements : sourceTop;
6918 for (
unsigned int x = 0; x < targetWidth; ++x)
6920 const TScale sx =
minmax(TScale(0), sourceX_T_targetXOffset + sourceX_T_targetX * TScale(x), sourceWidth_1);
6921 ocean_assert(sx >= TScale(0) && sx < TScale(sourceWidth));
6923 const unsigned int sLeft = (
unsigned int)sx;
6924 ocean_assert(sx >= TScale(sLeft));
6926 const TScale factorRight = sx - TScale(sLeft);
6927 ocean_assert(factorRight >= TScale(0) && factorRight <= TScale(1));
6929 const TScale factorLeft = TScale(1) - factorRight;
6930 ocean_assert(factorLeft >= TScale(0) && factorLeft <= TScale(1));
6932 const unsigned int sourceRightOffset = sLeft + 1u < sourceWidth ? tChannels : 0u;
6934 const T*
const sourceTopLeft = sourceTop + sLeft * tChannels;
6935 const T*
const sourceBottomLeft = sourceBottom + sLeft * tChannels;
6937 const TScale factorTopLeft = factorTop * factorLeft;
6938 const TScale factorTopRight = factorTop * factorRight;
6939 const TScale factorBottomLeft = factorBottom * factorLeft;
6940 const TScale factorBottomRight = factorBottom * factorRight;
6942 for (
unsigned int n = 0u; n < tChannels; ++n)
6944 target[n] = T(TScale(sourceTopLeft[n]) * factorTopLeft + TScale(sourceTopLeft[sourceRightOffset + n]) * factorTopRight
6945 + TScale(sourceBottomLeft[n]) * factorBottomLeft + TScale(sourceBottomLeft[sourceRightOffset + n]) * factorBottomRight);
6948 target += tChannels;
6951 target += targetPaddingElements;
6955 template <
unsigned int tChannels>
6956 void 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)
6958 static_assert(tChannels != 0u,
"Invalid channel number!");
6960 ocean_assert(firstTargetRow + numberTargetRows <= height);
6964 const unsigned int targetStrideElements = width * tChannels + targetPaddingElements;
6966 uint8_t zeroColor[tChannels] = {uint8_t(0)};
6967 const PixelType bColor = borderColor ? *(
const PixelType*)borderColor : *(
const PixelType*)zeroColor;
6970 const SquareMatrix2 rotationMatrix2(rotationMatrix3(0, 0), rotationMatrix3(1, 0), rotationMatrix3(0, 1), rotationMatrix3(1, 1));
6974 const Vector2 anchorPosition(horizontalAnchorPosition, verticalAnchorPosition);
6976 for (
unsigned int y = firstTargetRow; y < firstTargetRow + numberTargetRows; ++y)
6978 PixelType* targetPixel = (PixelType*)(target + y * targetStrideElements);
6982 for (
unsigned int x = 0; x < width; ++x)
6984 const Vector2 sourceLocation(anchorPosition + rotationMatrix2 * (
Vector2(
Scalar(x), floatY) - anchorPosition));
6986 if (sourceLocation.
x() >= 0 && sourceLocation.
y() >= 0 && sourceLocation.
x() <= width_1 && sourceLocation.
y() <= height_1)
6988 interpolatePixel8BitPerChannel<tChannels, PC_TOP_LEFT>(source, width, height, sourcePaddingElements, sourceLocation, (uint8_t*)(targetPixel));
6992 *targetPixel = bColor;
This class implements the abstract base class for all AnyCamera objects.
Definition: AnyCamera.h:130
virtual unsigned int width() const =0
Returns the width of the camera image.
virtual VectorT2< T > projectToImageIF(const VectorT3< T > &objectPoint) const =0
Projects a 3D object point into the camera frame.
virtual unsigned int height() const =0
Returns the height of the camera image.
virtual bool isValid() const =0
Returns whether this camera is valid.
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.
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:1521
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:1434
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:4285
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:1733
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:1893
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:1799
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:1833
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:1960
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:2464
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:1816
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:4507
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:1786
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:3577
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:2380
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:1770
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:3957
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:4351
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:4587
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:1657
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:4633
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:3327
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:4992
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:5407
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:5372
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:6956
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:1880
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:3259
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:1757
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:4681
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:1608
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:1621
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:4735
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:5231
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:1942
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:5352
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:1695
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:2139
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:5134
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:2228
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:2649
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:5187
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:4432
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:6832
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:2303
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:2053
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:1792
bool isValid() const
Returns whether this frame is valid.
Definition: Frame.h:4448
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:698
const T & y() const noexcept
Returns the y value.
Definition: Vector2.h:710
bool isEqual(const VectorT2< T > &vector, const T eps) const
Returns whether two vectors are equal up to a specified epsilon.
Definition: Vector2.h:746
const T & y() const noexcept
Returns the y value.
Definition: Vector3.h:812
const T & x() const noexcept
Returns the x value.
Definition: Vector3.h:800
const T & z() const noexcept
Returns the z value.
Definition: Vector3.h:824
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
PixelPositionT< int > PixelPositionI
Definition of a PixelPosition object with a data type allowing positive and negative coordinate value...
Definition: PixelPosition.h:41
@ 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:35
RotationT< Scalar > Rotation
Definition of the Rotation object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION flag either with ...
Definition: Rotation.h:31
float Scalar
Definition of a scalar type.
Definition: Math.h:128
VectorT3< Scalar > Vector3
Definition of a 3D vector.
Definition: Vector3.h:22
VectorT2< Scalar > Vector2
Definition of a 2D vector.
Definition: Vector2.h:21
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