mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
222 lines
7.4 KiB
222 lines
7.4 KiB
/* |
|
* By downloading, copying, installing or using the software you agree to this license. |
|
* If you do not agree to this license, do not download, install, |
|
* copy or use the software. |
|
* |
|
* |
|
* License Agreement |
|
* For Open Source Computer Vision Library |
|
* (3-clause BSD License) |
|
* |
|
* Copyright (C) 2014, NVIDIA Corporation, all rights reserved. |
|
* Third party copyrights are property of their respective owners. |
|
* |
|
* Redistribution and use in source and binary forms, with or without modification, |
|
* are permitted provided that the following conditions are met: |
|
* |
|
* * Redistributions of source code must retain the above copyright notice, |
|
* this list of conditions and the following disclaimer. |
|
* |
|
* * Redistributions in binary form must reproduce the above copyright notice, |
|
* this list of conditions and the following disclaimer in the documentation |
|
* and/or other materials provided with the distribution. |
|
* |
|
* * Neither the names of the copyright holders nor the names of the contributors |
|
* may be used to endorse or promote products derived from this software |
|
* without specific prior written permission. |
|
* |
|
* This software is provided by the copyright holders and contributors "as is" and |
|
* any express or implied warranties, including, but not limited to, the implied |
|
* warranties of merchantability and fitness for a particular purpose are disclaimed. |
|
* In no event shall copyright holders or contributors be liable for any direct, |
|
* indirect, incidental, special, exemplary, or consequential damages |
|
* (including, but not limited to, procurement of substitute goods or services; |
|
* loss of use, data, or profits; or business interruption) however caused |
|
* and on any theory of liability, whether in contract, strict liability, |
|
* or tort (including negligence or otherwise) arising in any way out of |
|
* the use of this software, even if advised of the possibility of such damage. |
|
*/ |
|
|
|
#include "common.hpp" |
|
#include "vtransform.hpp" |
|
|
|
#include <cstring> |
|
|
|
namespace CAROTENE_NS { |
|
|
|
bool isFlipSupported(FLIP_MODE flipMode, u32 elemSize) |
|
{ |
|
bool supportedElemSize = (elemSize == 1) || (elemSize == 2) || (elemSize == 3) || (elemSize == 4); |
|
return isSupportedConfiguration() && |
|
((supportedElemSize && ((flipMode == FLIP_BOTH_MODE) || (flipMode == FLIP_HORIZONTAL_MODE))) || |
|
(flipMode == FLIP_VERTICAL_MODE)); |
|
} |
|
|
|
#ifdef CAROTENE_NEON |
|
|
|
namespace { |
|
|
|
template <typename T> |
|
void flip(const Size2D & size, |
|
const void * srcBase, ptrdiff_t srcStride, |
|
void * dstBase, ptrdiff_t dstStride, |
|
FLIP_MODE flipMode) |
|
{ |
|
using namespace internal; |
|
|
|
typedef typename VecTraits<T>::vec128 vec128; |
|
typedef typename VecTraits<T>::vec64 vec64; |
|
|
|
u32 step_base = 16 / sizeof(T), step_tail = 8 / sizeof(T); |
|
size_t roiw_base = size.width >= (step_base - 1) ? size.width - step_base + 1 : 0; |
|
size_t roiw_tail = size.width >= (step_tail - 1) ? size.width - step_tail + 1 : 0; |
|
|
|
for (size_t i = 0; i < size.height; ++i) |
|
{ |
|
const T * src = getRowPtr((const T *)srcBase, srcStride, i); |
|
T * dst = getRowPtr((T *)dstBase, dstStride, (flipMode & FLIP_VERTICAL_MODE) != 0 ? size.height - i - 1 : i); |
|
size_t js = 0, jd = size.width; |
|
|
|
for (; js < roiw_base; js += step_base, jd -= step_base) |
|
{ |
|
prefetch(src + js); |
|
|
|
vec128 v_src = vld1q(src + js); |
|
vec128 v_dst = vrev64q(v_src); |
|
v_dst = vcombine(vget_high(v_dst), vget_low(v_dst)); |
|
vst1q(dst + jd - step_base, v_dst); |
|
} |
|
for (; js < roiw_tail; js += step_tail, jd -= step_tail) |
|
{ |
|
vec64 v_src = vld1(src + js); |
|
vst1(dst + jd - step_tail, vrev64(v_src)); |
|
} |
|
|
|
for (--jd; js < size.width; ++js, --jd) |
|
dst[jd] = src[js]; |
|
} |
|
} |
|
|
|
template <typename T> |
|
void flip3(const Size2D & size, |
|
const void * srcBase, ptrdiff_t srcStride, |
|
void * dstBase, ptrdiff_t dstStride, |
|
FLIP_MODE flipMode) |
|
{ |
|
using namespace internal; |
|
|
|
#ifndef __ANDROID__ |
|
typedef typename VecTraits<T, 3>::vec128 vec128; |
|
#endif |
|
typedef typename VecTraits<T, 3>::vec64 vec64; |
|
|
|
#ifndef __ANDROID__ |
|
u32 step_base = 16 / sizeof(T), step_base3 = step_base * 3; |
|
size_t roiw_base = size.width >= (step_base - 1) ? size.width - step_base + 1 : 0; |
|
#endif |
|
u32 step_tail = 8 / sizeof(T), step_tail3 = step_tail * 3; |
|
size_t roiw_tail = size.width >= (step_tail - 1) ? size.width - step_tail + 1 : 0; |
|
|
|
for (size_t i = 0; i < size.height; ++i) |
|
{ |
|
const T * src = getRowPtr((const T *)srcBase, srcStride, i); |
|
T * dst = getRowPtr((T *)dstBase, dstStride, (flipMode & FLIP_VERTICAL_MODE) != 0 ? size.height - i - 1 : i); |
|
size_t j = 0, js = 0, jd = size.width * 3; |
|
|
|
#ifndef __ANDROID__ |
|
for (; j < roiw_base; j += step_base, js += step_base3, jd -= step_base3) |
|
{ |
|
prefetch(src + js); |
|
|
|
vec128 v_src = vld3q(src + js), v_dst; |
|
v_src.val[0] = vrev64q(v_src.val[0]); |
|
v_src.val[1] = vrev64q(v_src.val[1]); |
|
v_src.val[2] = vrev64q(v_src.val[2]); |
|
|
|
v_dst.val[0] = vcombine(vget_high(v_src.val[0]), vget_low(v_src.val[0])); |
|
v_dst.val[1] = vcombine(vget_high(v_src.val[1]), vget_low(v_src.val[1])); |
|
v_dst.val[2] = vcombine(vget_high(v_src.val[2]), vget_low(v_src.val[2])); |
|
|
|
vst3q(dst + jd - step_base3, v_dst); |
|
} |
|
#endif // __ANDROID__ |
|
|
|
for (; j < roiw_tail; j += step_tail, js += step_tail3, jd -= step_tail3) |
|
{ |
|
vec64 v_src = vld3(src + js), v_dst; |
|
v_dst.val[0] = vrev64(v_src.val[0]); |
|
v_dst.val[1] = vrev64(v_src.val[1]); |
|
v_dst.val[2] = vrev64(v_src.val[2]); |
|
|
|
vst3(dst + jd - step_tail3, v_dst); |
|
} |
|
|
|
for (jd -= 3; j < size.width; ++j, js += 3, jd -= 3) |
|
{ |
|
dst[jd] = src[js]; |
|
dst[jd + 1] = src[js + 1]; |
|
dst[jd + 2] = src[js + 2]; |
|
} |
|
} |
|
} |
|
|
|
typedef void (* flipFunc)(const Size2D &size, |
|
const void * srcBase, ptrdiff_t srcStride, |
|
void * dstBase, ptrdiff_t dstStride, |
|
FLIP_MODE flipMode); |
|
|
|
} // namespace |
|
|
|
#endif |
|
|
|
void flip(const Size2D &size, |
|
const u8 * srcBase, ptrdiff_t srcStride, |
|
u8 * dstBase, ptrdiff_t dstStride, |
|
FLIP_MODE flipMode, u32 elemSize) |
|
{ |
|
internal::assertSupportedConfiguration(isFlipSupported(flipMode, elemSize)); |
|
#ifdef CAROTENE_NEON |
|
|
|
if (flipMode == FLIP_VERTICAL_MODE) |
|
{ |
|
for (size_t y = 0; y < size.height; ++y) |
|
{ |
|
const u8 * src_row = internal::getRowPtr(srcBase, srcStride, y); |
|
u8 * dst_row = internal::getRowPtr(dstBase, dstStride, size.height - y - 1); |
|
|
|
std::memcpy(dst_row, src_row, elemSize * size.width); |
|
} |
|
return; |
|
} |
|
|
|
flipFunc func = NULL; |
|
|
|
if (elemSize == (u32)sizeof(u8)) |
|
func = &flip<u8>; |
|
if (elemSize == (u32)sizeof(u16)) |
|
func = &flip<u16>; |
|
if (elemSize == (u32)sizeof(u32)) |
|
func = &flip<u32>; |
|
if (elemSize == (u32)sizeof(u8) * 3) |
|
func = &flip3<u8>; |
|
|
|
if (func == NULL) |
|
return; |
|
|
|
func(size, |
|
srcBase, srcStride, |
|
dstBase, dstStride, |
|
flipMode); |
|
|
|
#else |
|
(void)size; |
|
(void)srcBase; |
|
(void)srcStride; |
|
(void)dstBase; |
|
(void)dstStride; |
|
(void)flipMode; |
|
(void)elemSize; |
|
#endif |
|
} |
|
|
|
} // namespace CAROTENE_NS
|
|
|