/* * 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 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 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::vec128 vec128; typedef typename VecTraits::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 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::vec128 vec128; #endif typedef typename VecTraits::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; if (elemSize == (u32)sizeof(u16)) func = &flip; if (elemSize == (u32)sizeof(u32)) func = &flip; if (elemSize == (u32)sizeof(u8) * 3) func = &flip3; 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