|
|
|
@ -1725,24 +1725,182 @@ struct Luv2RGB_b |
|
|
|
|
|
|
|
|
|
//////////////////////////// Bayer Pattern -> RGB conversion /////////////////////////////
|
|
|
|
|
|
|
|
|
|
static void Bayer2Gray_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
template<typename T> |
|
|
|
|
class SIMDBayerStubInterpolator_ |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
int bayer2Gray(const T*, int, T*, int, int, int, int) const |
|
|
|
|
{ |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int bayer2RGB(const T*, int, T*, int, int) const |
|
|
|
|
{ |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#if CV_SSE2 |
|
|
|
|
class SIMDBayerInterpolator_8u |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
SIMDBayerInterpolator_8u() |
|
|
|
|
{ |
|
|
|
|
use_simd = checkHardwareSupport(CV_CPU_SSE2); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int bayer2Gray(const uchar* bayer, int bayer_step, uchar* dst, |
|
|
|
|
int width, int bcoeff, int gcoeff, int rcoeff) const |
|
|
|
|
{ |
|
|
|
|
if( !use_simd ) |
|
|
|
|
return 0; |
|
|
|
|
|
|
|
|
|
__m128i _b2y = _mm_set1_epi16((short)(rcoeff*2)); |
|
|
|
|
__m128i _g2y = _mm_set1_epi16((short)(gcoeff*2)); |
|
|
|
|
__m128i _r2y = _mm_set1_epi16((short)(bcoeff*2)); |
|
|
|
|
const uchar* bayer_end = bayer + width; |
|
|
|
|
|
|
|
|
|
for( ; bayer <= bayer_end - 18; bayer += 14, dst += 14 ) |
|
|
|
|
{ |
|
|
|
|
__m128i r0 = _mm_loadu_si128((const __m128i*)bayer); |
|
|
|
|
__m128i r1 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step)); |
|
|
|
|
__m128i r2 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step*2)); |
|
|
|
|
|
|
|
|
|
__m128i b1 = _mm_add_epi16(_mm_srli_epi16(_mm_slli_epi16(r0, 8), 8), |
|
|
|
|
_mm_srli_epi16(_mm_slli_epi16(r2, 8), 8)); |
|
|
|
|
__m128i b0 = _mm_add_epi16(b1, _mm_srli_si128(b1, 2)); |
|
|
|
|
b1 = _mm_slli_epi16(_mm_srli_si128(b1, 2), 1); |
|
|
|
|
|
|
|
|
|
__m128i g0 = _mm_add_epi16(_mm_srli_epi16(r0, 8), _mm_srli_epi16(r2, 8)); |
|
|
|
|
__m128i g1 = _mm_srli_epi16(_mm_slli_epi16(r1, 8), 8); |
|
|
|
|
g0 = _mm_add_epi16(g0, _mm_add_epi16(g1, _mm_srli_si128(g1, 2))); |
|
|
|
|
g1 = _mm_slli_epi16(_mm_srli_si128(g1, 2), 2); |
|
|
|
|
|
|
|
|
|
r0 = _mm_srli_epi16(r1, 8); |
|
|
|
|
r1 = _mm_slli_epi16(_mm_add_epi16(r0, _mm_srli_si128(r0, 2)), 1); |
|
|
|
|
r0 = _mm_slli_epi16(r0, 2); |
|
|
|
|
|
|
|
|
|
g0 = _mm_add_epi16(_mm_mulhi_epi16(b0, _b2y), _mm_mulhi_epi16(g0, _g2y)); |
|
|
|
|
g1 = _mm_add_epi16(_mm_mulhi_epi16(b1, _b2y), _mm_mulhi_epi16(g1, _g2y)); |
|
|
|
|
g0 = _mm_add_epi16(g0, _mm_mulhi_epi16(r0, _r2y)); |
|
|
|
|
g1 = _mm_add_epi16(g1, _mm_mulhi_epi16(r1, _r2y)); |
|
|
|
|
g0 = _mm_srli_epi16(g0, 1); |
|
|
|
|
g1 = _mm_srli_epi16(g1, 1); |
|
|
|
|
g0 = _mm_packus_epi16(g0, g0); |
|
|
|
|
g1 = _mm_packus_epi16(g1, g1); |
|
|
|
|
g0 = _mm_unpacklo_epi8(g0, g1); |
|
|
|
|
_mm_storeu_si128((__m128i*)dst, g0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return (int)(bayer - (bayer_end - width)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int bayer2RGB(const uchar* bayer, int bayer_step, uchar* dst, int width, int blue) const |
|
|
|
|
{ |
|
|
|
|
if( !use_simd ) |
|
|
|
|
return 0; |
|
|
|
|
/*
|
|
|
|
|
B G B G | B G B G | B G B G | B G B G |
|
|
|
|
G R G R | G R G R | G R G R | G R G R |
|
|
|
|
B G B G | B G B G | B G B G | B G B G |
|
|
|
|
*/ |
|
|
|
|
__m128i delta1 = _mm_set1_epi16(1), delta2 = _mm_set1_epi16(2); |
|
|
|
|
__m128i mask = _mm_set1_epi16(blue < 0 ? -1 : 0), z = _mm_setzero_si128(); |
|
|
|
|
__m128i masklo = _mm_set1_epi16(0x00ff); |
|
|
|
|
const uchar* bayer_end = bayer + width; |
|
|
|
|
|
|
|
|
|
for( ; bayer <= bayer_end - 18; bayer += 14, dst += 42 ) |
|
|
|
|
{ |
|
|
|
|
__m128i r0 = _mm_loadu_si128((const __m128i*)bayer); |
|
|
|
|
__m128i r1 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step)); |
|
|
|
|
__m128i r2 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step*2)); |
|
|
|
|
|
|
|
|
|
__m128i b1 = _mm_add_epi16(_mm_and_si128(r0, masklo), _mm_and_si128(r2, masklo)); |
|
|
|
|
__m128i b0 = _mm_add_epi16(b1, _mm_srli_si128(b1, 2)); |
|
|
|
|
b1 = _mm_srli_si128(b1, 2); |
|
|
|
|
b1 = _mm_srli_epi16(_mm_add_epi16(b1, delta1), 1); |
|
|
|
|
b0 = _mm_srli_epi16(_mm_add_epi16(b0, delta2), 2); |
|
|
|
|
b0 = _mm_packus_epi16(b0, b1); |
|
|
|
|
|
|
|
|
|
__m128i g0 = _mm_add_epi16(_mm_srli_epi16(r0, 8), _mm_srli_epi16(r2, 8)); |
|
|
|
|
__m128i g1 = _mm_and_si128(r1, masklo); |
|
|
|
|
g0 = _mm_add_epi16(g0, _mm_add_epi16(g1, _mm_srli_si128(g1, 2))); |
|
|
|
|
g1 = _mm_srli_si128(g1, 2); |
|
|
|
|
g0 = _mm_srli_epi16(_mm_add_epi16(g0, delta2), 2); |
|
|
|
|
g0 = _mm_packus_epi16(g0, g1); |
|
|
|
|
|
|
|
|
|
r0 = _mm_srli_epi16(r1, 8); |
|
|
|
|
r1 = _mm_add_epi16(r0, _mm_srli_si128(r0, 2)); |
|
|
|
|
r1 = _mm_srli_epi16(_mm_add_epi16(r1, delta1), 1); |
|
|
|
|
r0 = _mm_packus_epi16(r0, r1); |
|
|
|
|
|
|
|
|
|
b1 = _mm_and_si128(_mm_xor_si128(b0, r0), mask); |
|
|
|
|
b0 = _mm_xor_si128(b0, b1); |
|
|
|
|
r0 = _mm_xor_si128(r0, b1); |
|
|
|
|
|
|
|
|
|
// b1 g1 b1 g1 ...
|
|
|
|
|
b1 = _mm_unpackhi_epi8(b0, g0); |
|
|
|
|
// b0 g0 b2 g2 b4 g4 ....
|
|
|
|
|
b0 = _mm_unpacklo_epi8(b0, g0); |
|
|
|
|
|
|
|
|
|
// r1 0 r3 0 ...
|
|
|
|
|
r1 = _mm_unpackhi_epi8(r0, z); |
|
|
|
|
// r0 0 r2 0 r4 0 ...
|
|
|
|
|
r0 = _mm_unpacklo_epi8(r0, z); |
|
|
|
|
|
|
|
|
|
// 0 b0 g0 r0 0 b2 g2 r2 0 ...
|
|
|
|
|
g0 = _mm_slli_si128(_mm_unpacklo_epi16(b0, r0), 1); |
|
|
|
|
// 0 b8 g8 r8 0 b10 g10 r10 0 ...
|
|
|
|
|
g1 = _mm_slli_si128(_mm_unpackhi_epi16(b0, r0), 1); |
|
|
|
|
|
|
|
|
|
// b1 g1 r1 0 b3 g3 r3 ....
|
|
|
|
|
r0 = _mm_unpacklo_epi16(b1, r1); |
|
|
|
|
// b9 g9 r9 0 ...
|
|
|
|
|
r1 = _mm_unpackhi_epi16(b1, r1); |
|
|
|
|
|
|
|
|
|
b0 = _mm_srli_si128(_mm_unpacklo_epi32(g0, r0), 1); |
|
|
|
|
b1 = _mm_srli_si128(_mm_unpackhi_epi32(g0, r0), 1); |
|
|
|
|
|
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+0), b0); |
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*1), _mm_srli_si128(b0, 8)); |
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*2), b1); |
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*3), _mm_srli_si128(b1, 8)); |
|
|
|
|
|
|
|
|
|
g0 = _mm_srli_si128(_mm_unpacklo_epi32(g1, r1), 1); |
|
|
|
|
g1 = _mm_srli_si128(_mm_unpackhi_epi32(g1, r1), 1); |
|
|
|
|
|
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*4), g0); |
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*5), _mm_srli_si128(g0, 8)); |
|
|
|
|
|
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*6), g1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return (int)(bayer - (bayer_end - width)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool use_simd; |
|
|
|
|
}; |
|
|
|
|
#else |
|
|
|
|
typedef SIMDBayerStubInterpolator_<uchar> SIMDBayerInterpolator_8u; |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
template<typename T, class SIMDInterpolator> |
|
|
|
|
static void Bayer2Gray_( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
{ |
|
|
|
|
SIMDInterpolator vecOp; |
|
|
|
|
const int R2Y = 4899; |
|
|
|
|
const int G2Y = 9617; |
|
|
|
|
const int B2Y = 1868; |
|
|
|
|
const int SHIFT = 14; |
|
|
|
|
|
|
|
|
|
const uchar* bayer0 = srcmat.data; |
|
|
|
|
int bayer_step = (int)srcmat.step; |
|
|
|
|
uchar* dst0 = dstmat.data; |
|
|
|
|
int dst_step = (int)dstmat.step; |
|
|
|
|
const T* bayer0 = (const T*)srcmat.data; |
|
|
|
|
int bayer_step = (int)(srcmat.step/sizeof(T)); |
|
|
|
|
T* dst0 = (T*)dstmat.data; |
|
|
|
|
int dst_step = (int)(dstmat.step/sizeof(T)); |
|
|
|
|
Size size = srcmat.size(); |
|
|
|
|
int bcoeff = B2Y, rcoeff = R2Y; |
|
|
|
|
int start_with_green = code == CV_BayerGB2GRAY || code == CV_BayerGR2GRAY; |
|
|
|
|
bool brow = true; |
|
|
|
|
#if CV_SSE2 |
|
|
|
|
bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if( code != CV_BayerBG2GRAY && code != CV_BayerGB2GRAY ) |
|
|
|
|
{ |
|
|
|
@ -1756,10 +1914,10 @@ static void Bayer2Gray_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
|
|
|
|
|
for( ; size.height-- > 0; bayer0 += bayer_step, dst0 += dst_step ) |
|
|
|
|
{ |
|
|
|
|
int t0, t1, t2; |
|
|
|
|
const uchar* bayer = bayer0; |
|
|
|
|
uchar* dst = dst0; |
|
|
|
|
const uchar* bayer_end = bayer + size.width; |
|
|
|
|
unsigned t0, t1, t2; |
|
|
|
|
const T* bayer = bayer0; |
|
|
|
|
T* dst = dst0; |
|
|
|
|
const T* bayer_end = bayer + size.width; |
|
|
|
|
|
|
|
|
|
if( size.width <= 0 ) |
|
|
|
|
{ |
|
|
|
@ -1773,63 +1931,26 @@ static void Bayer2Gray_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
t1 = (bayer[bayer_step] + bayer[bayer_step+2])*bcoeff; |
|
|
|
|
t2 = bayer[bayer_step+1]*(2*G2Y); |
|
|
|
|
|
|
|
|
|
dst[0] = (uchar)CV_DESCALE(t0 + t1 + t2, SHIFT+1); |
|
|
|
|
dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+1); |
|
|
|
|
bayer++; |
|
|
|
|
dst++; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if CV_SSE2 |
|
|
|
|
if( haveSSE2 ) |
|
|
|
|
{ |
|
|
|
|
__m128i _b2y = _mm_set1_epi16((short)(rcoeff*2)); |
|
|
|
|
__m128i _g2y = _mm_set1_epi16((short)(G2Y*2)); |
|
|
|
|
__m128i _r2y = _mm_set1_epi16((short)(bcoeff*2)); |
|
|
|
|
|
|
|
|
|
for( ; bayer <= bayer_end - 18; bayer += 14, dst += 14 ) |
|
|
|
|
{ |
|
|
|
|
__m128i r0 = _mm_loadu_si128((const __m128i*)bayer); |
|
|
|
|
__m128i r1 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step)); |
|
|
|
|
__m128i r2 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step*2)); |
|
|
|
|
|
|
|
|
|
__m128i b1 = _mm_add_epi16(_mm_srli_epi16(_mm_slli_epi16(r0, 8), 8), |
|
|
|
|
_mm_srli_epi16(_mm_slli_epi16(r2, 8), 8)); |
|
|
|
|
__m128i b0 = _mm_add_epi16(b1, _mm_srli_si128(b1, 2)); |
|
|
|
|
b1 = _mm_slli_epi16(_mm_srli_si128(b1, 2), 1); |
|
|
|
|
|
|
|
|
|
__m128i g0 = _mm_add_epi16(_mm_srli_epi16(r0, 8), _mm_srli_epi16(r2, 8)); |
|
|
|
|
__m128i g1 = _mm_srli_epi16(_mm_slli_epi16(r1, 8), 8); |
|
|
|
|
g0 = _mm_add_epi16(g0, _mm_add_epi16(g1, _mm_srli_si128(g1, 2))); |
|
|
|
|
g1 = _mm_slli_epi16(_mm_srli_si128(g1, 2), 2); |
|
|
|
|
|
|
|
|
|
r0 = _mm_srli_epi16(r1, 8); |
|
|
|
|
r1 = _mm_slli_epi16(_mm_add_epi16(r0, _mm_srli_si128(r0, 2)), 1); |
|
|
|
|
r0 = _mm_slli_epi16(r0, 2); |
|
|
|
|
|
|
|
|
|
g0 = _mm_add_epi16(_mm_mulhi_epi16(b0, _b2y), _mm_mulhi_epi16(g0, _g2y)); |
|
|
|
|
g1 = _mm_add_epi16(_mm_mulhi_epi16(b1, _b2y), _mm_mulhi_epi16(g1, _g2y)); |
|
|
|
|
g0 = _mm_add_epi16(g0, _mm_mulhi_epi16(r0, _r2y)); |
|
|
|
|
g1 = _mm_add_epi16(g1, _mm_mulhi_epi16(r1, _r2y)); |
|
|
|
|
g0 = _mm_srli_epi16(g0, 1); |
|
|
|
|
g1 = _mm_srli_epi16(g1, 1); |
|
|
|
|
g0 = _mm_packus_epi16(g0, g0); |
|
|
|
|
g1 = _mm_packus_epi16(g1, g1); |
|
|
|
|
g0 = _mm_unpacklo_epi8(g0, g1); |
|
|
|
|
_mm_storeu_si128((__m128i*)dst, g0); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
int delta = vecOp.bayer2Gray(bayer, bayer_step, dst, size.width, bcoeff, G2Y, rcoeff); |
|
|
|
|
bayer += delta; |
|
|
|
|
dst += delta; |
|
|
|
|
|
|
|
|
|
for( ; bayer <= bayer_end - 2; bayer += 2, dst += 2 ) |
|
|
|
|
{ |
|
|
|
|
t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] + bayer[bayer_step*2+2])*rcoeff; |
|
|
|
|
t1 = (bayer[1] + bayer[bayer_step] + bayer[bayer_step+2] + bayer[bayer_step*2+1])*G2Y; |
|
|
|
|
t2 = bayer[bayer_step+1]*(4*bcoeff); |
|
|
|
|
dst[0] = (uchar)CV_DESCALE(t0 + t1 + t2, SHIFT+2); |
|
|
|
|
dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+2); |
|
|
|
|
|
|
|
|
|
t0 = (bayer[2] + bayer[bayer_step*2+2])*rcoeff; |
|
|
|
|
t1 = (bayer[bayer_step+1] + bayer[bayer_step+3])*bcoeff; |
|
|
|
|
t2 = bayer[bayer_step+2]*(2*G2Y); |
|
|
|
|
dst[1] = (uchar)CV_DESCALE(t0 + t1 + t2, SHIFT+1); |
|
|
|
|
dst[1] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if( bayer < bayer_end ) |
|
|
|
@ -1837,7 +1958,7 @@ static void Bayer2Gray_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
t0 = (bayer[0] + bayer[2] + bayer[bayer_step*2] + bayer[bayer_step*2+2])*rcoeff; |
|
|
|
|
t1 = (bayer[1] + bayer[bayer_step] + bayer[bayer_step+2] + bayer[bayer_step*2+1])*G2Y; |
|
|
|
|
t2 = bayer[bayer_step+1]*(4*bcoeff); |
|
|
|
|
dst[0] = (uchar)CV_DESCALE(t0 + t1 + t2, SHIFT+2); |
|
|
|
|
dst[0] = (T)CV_DESCALE(t0 + t1 + t2, SHIFT+2); |
|
|
|
|
bayer++; |
|
|
|
|
dst++; |
|
|
|
|
} |
|
|
|
@ -1851,7 +1972,7 @@ static void Bayer2Gray_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size = dstmat.size(); |
|
|
|
|
dst0 = dstmat.data; |
|
|
|
|
dst0 = (T*)dstmat.data; |
|
|
|
|
if( size.height > 2 ) |
|
|
|
|
for( int i = 0; i < size.width; i++ ) |
|
|
|
|
{ |
|
|
|
@ -1865,19 +1986,17 @@ static void Bayer2Gray_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void Bayer2RGB_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
template<typename T, class SIMDInterpolator>
|
|
|
|
|
static void Bayer2RGB_( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
{ |
|
|
|
|
const uchar* bayer0 = srcmat.data; |
|
|
|
|
int bayer_step = (int)srcmat.step; |
|
|
|
|
uchar* dst0 = dstmat.data; |
|
|
|
|
int dst_step = (int)dstmat.step; |
|
|
|
|
SIMDInterpolator vecOp; |
|
|
|
|
const T* bayer0 = (const T*)srcmat.data; |
|
|
|
|
int bayer_step = (int)(srcmat.step/sizeof(T)); |
|
|
|
|
T* dst0 = (T*)dstmat.data; |
|
|
|
|
int dst_step = (int)(dstmat.step/sizeof(T)); |
|
|
|
|
Size size = srcmat.size(); |
|
|
|
|
int blue = code == CV_BayerBG2BGR || code == CV_BayerGB2BGR ? -1 : 1; |
|
|
|
|
int start_with_green = code == CV_BayerGB2BGR || code == CV_BayerGR2BGR; |
|
|
|
|
#if CV_SSE2 |
|
|
|
|
bool haveSSE2 = checkHardwareSupport(CV_CPU_SSE2); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
dst0 += dst_step + 3 + 1; |
|
|
|
|
size.height -= 2; |
|
|
|
@ -1886,9 +2005,9 @@ static void Bayer2RGB_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
for( ; size.height-- > 0; bayer0 += bayer_step, dst0 += dst_step ) |
|
|
|
|
{ |
|
|
|
|
int t0, t1; |
|
|
|
|
const uchar* bayer = bayer0; |
|
|
|
|
uchar* dst = dst0; |
|
|
|
|
const uchar* bayer_end = bayer + size.width; |
|
|
|
|
const T* bayer = bayer0; |
|
|
|
|
T* dst = dst0; |
|
|
|
|
const T* bayer_end = bayer + size.width; |
|
|
|
|
|
|
|
|
|
if( size.width <= 0 ) |
|
|
|
|
{ |
|
|
|
@ -1901,93 +2020,17 @@ static void Bayer2RGB_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
{ |
|
|
|
|
t0 = (bayer[1] + bayer[bayer_step*2+1] + 1) >> 1; |
|
|
|
|
t1 = (bayer[bayer_step] + bayer[bayer_step+2] + 1) >> 1; |
|
|
|
|
dst[-blue] = (uchar)t0; |
|
|
|
|
dst[-blue] = (T)t0; |
|
|
|
|
dst[0] = bayer[bayer_step+1]; |
|
|
|
|
dst[blue] = (uchar)t1; |
|
|
|
|
dst[blue] = (T)t1; |
|
|
|
|
bayer++; |
|
|
|
|
dst += 3; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if CV_SSE2 |
|
|
|
|
if( haveSSE2 ) |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
B G B G | B G B G | B G B G | B G B G |
|
|
|
|
G R G R | G R G R | G R G R | G R G R |
|
|
|
|
B G B G | B G B G | B G B G | B G B G |
|
|
|
|
*/ |
|
|
|
|
__m128i delta1 = _mm_set1_epi16(1), delta2 = _mm_set1_epi16(2); |
|
|
|
|
__m128i mask = _mm_set1_epi16(blue < 0 ? -1 : 0), z = _mm_setzero_si128(); |
|
|
|
|
__m128i masklo = _mm_set1_epi16(0x00ff); |
|
|
|
|
|
|
|
|
|
for( ; bayer <= bayer_end - 18; bayer += 14, dst += 42 ) |
|
|
|
|
{ |
|
|
|
|
__m128i r0 = _mm_loadu_si128((const __m128i*)bayer); |
|
|
|
|
__m128i r1 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step)); |
|
|
|
|
__m128i r2 = _mm_loadu_si128((const __m128i*)(bayer+bayer_step*2)); |
|
|
|
|
|
|
|
|
|
__m128i b1 = _mm_add_epi16(_mm_and_si128(r0, masklo), _mm_and_si128(r2, masklo)); |
|
|
|
|
__m128i b0 = _mm_add_epi16(b1, _mm_srli_si128(b1, 2)); |
|
|
|
|
b1 = _mm_srli_si128(b1, 2); |
|
|
|
|
b1 = _mm_srli_epi16(_mm_add_epi16(b1, delta1), 1); |
|
|
|
|
b0 = _mm_srli_epi16(_mm_add_epi16(b0, delta2), 2); |
|
|
|
|
b0 = _mm_packus_epi16(b0, b1); |
|
|
|
|
|
|
|
|
|
__m128i g0 = _mm_add_epi16(_mm_srli_epi16(r0, 8), _mm_srli_epi16(r2, 8)); |
|
|
|
|
__m128i g1 = _mm_and_si128(r1, masklo); |
|
|
|
|
g0 = _mm_add_epi16(g0, _mm_add_epi16(g1, _mm_srli_si128(g1, 2))); |
|
|
|
|
g1 = _mm_srli_si128(g1, 2); |
|
|
|
|
g0 = _mm_srli_epi16(_mm_add_epi16(g0, delta2), 2); |
|
|
|
|
g0 = _mm_packus_epi16(g0, g1); |
|
|
|
|
|
|
|
|
|
r0 = _mm_srli_epi16(r1, 8); |
|
|
|
|
r1 = _mm_add_epi16(r0, _mm_srli_si128(r0, 2)); |
|
|
|
|
r1 = _mm_srli_epi16(_mm_add_epi16(r1, delta1), 1); |
|
|
|
|
r0 = _mm_packus_epi16(r0, r1); |
|
|
|
|
|
|
|
|
|
b1 = _mm_and_si128(_mm_xor_si128(b0, r0), mask); |
|
|
|
|
b0 = _mm_xor_si128(b0, b1); |
|
|
|
|
r0 = _mm_xor_si128(r0, b1); |
|
|
|
|
|
|
|
|
|
// b1 g1 b1 g1 ...
|
|
|
|
|
b1 = _mm_unpackhi_epi8(b0, g0); |
|
|
|
|
// b0 g0 b2 g2 b4 g4 ....
|
|
|
|
|
b0 = _mm_unpacklo_epi8(b0, g0); |
|
|
|
|
|
|
|
|
|
// r1 0 r3 0 ...
|
|
|
|
|
r1 = _mm_unpackhi_epi8(r0, z); |
|
|
|
|
// r0 0 r2 0 r4 0 ...
|
|
|
|
|
r0 = _mm_unpacklo_epi8(r0, z); |
|
|
|
|
|
|
|
|
|
// 0 b0 g0 r0 0 b2 g2 r2 0 ...
|
|
|
|
|
g0 = _mm_slli_si128(_mm_unpacklo_epi16(b0, r0), 1); |
|
|
|
|
// 0 b8 g8 r8 0 b10 g10 r10 0 ...
|
|
|
|
|
g1 = _mm_slli_si128(_mm_unpackhi_epi16(b0, r0), 1); |
|
|
|
|
|
|
|
|
|
// b1 g1 r1 0 b3 g3 r3 ....
|
|
|
|
|
r0 = _mm_unpacklo_epi16(b1, r1); |
|
|
|
|
// b9 g9 r9 0 ...
|
|
|
|
|
r1 = _mm_unpackhi_epi16(b1, r1); |
|
|
|
|
|
|
|
|
|
b0 = _mm_srli_si128(_mm_unpacklo_epi32(g0, r0), 1); |
|
|
|
|
b1 = _mm_srli_si128(_mm_unpackhi_epi32(g0, r0), 1); |
|
|
|
|
int delta = vecOp.bayer2RGB(bayer, bayer_step, dst, size.width, blue); |
|
|
|
|
bayer += delta; |
|
|
|
|
dst += delta*3; |
|
|
|
|
|
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+0), b0); |
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*1), _mm_srli_si128(b0, 8)); |
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*2), b1); |
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*3), _mm_srli_si128(b1, 8)); |
|
|
|
|
|
|
|
|
|
g0 = _mm_srli_si128(_mm_unpacklo_epi32(g1, r1), 1); |
|
|
|
|
g1 = _mm_srli_si128(_mm_unpackhi_epi32(g1, r1), 1); |
|
|
|
|
|
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*4), g0); |
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*5), _mm_srli_si128(g0, 8)); |
|
|
|
|
|
|
|
|
|
_mm_storel_epi64((__m128i*)(dst-1+6*6), g1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
if( blue > 0 ) |
|
|
|
|
{ |
|
|
|
|
for( ; bayer <= bayer_end - 2; bayer += 2, dst += 6 ) |
|
|
|
@ -1996,15 +2039,15 @@ static void Bayer2RGB_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
bayer[bayer_step*2+2] + 2) >> 2; |
|
|
|
|
t1 = (bayer[1] + bayer[bayer_step] + |
|
|
|
|
bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2; |
|
|
|
|
dst[-1] = (uchar)t0; |
|
|
|
|
dst[0] = (uchar)t1; |
|
|
|
|
dst[-1] = (T)t0; |
|
|
|
|
dst[0] = (T)t1; |
|
|
|
|
dst[1] = bayer[bayer_step+1]; |
|
|
|
|
|
|
|
|
|
t0 = (bayer[2] + bayer[bayer_step*2+2] + 1) >> 1; |
|
|
|
|
t1 = (bayer[bayer_step+1] + bayer[bayer_step+3] + 1) >> 1; |
|
|
|
|
dst[2] = (uchar)t0; |
|
|
|
|
dst[2] = (T)t0; |
|
|
|
|
dst[3] = bayer[bayer_step+2]; |
|
|
|
|
dst[4] = (uchar)t1; |
|
|
|
|
dst[4] = (T)t1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
@ -2015,15 +2058,15 @@ static void Bayer2RGB_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
bayer[bayer_step*2+2] + 2) >> 2; |
|
|
|
|
t1 = (bayer[1] + bayer[bayer_step] + |
|
|
|
|
bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2; |
|
|
|
|
dst[1] = (uchar)t0; |
|
|
|
|
dst[0] = (uchar)t1; |
|
|
|
|
dst[1] = (T)t0; |
|
|
|
|
dst[0] = (T)t1; |
|
|
|
|
dst[-1] = bayer[bayer_step+1]; |
|
|
|
|
|
|
|
|
|
t0 = (bayer[2] + bayer[bayer_step*2+2] + 1) >> 1; |
|
|
|
|
t1 = (bayer[bayer_step+1] + bayer[bayer_step+3] + 1) >> 1; |
|
|
|
|
dst[4] = (uchar)t0; |
|
|
|
|
dst[4] = (T)t0; |
|
|
|
|
dst[3] = bayer[bayer_step+2]; |
|
|
|
|
dst[2] = (uchar)t1; |
|
|
|
|
dst[2] = (T)t1; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2033,8 +2076,8 @@ static void Bayer2RGB_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
bayer[bayer_step*2+2] + 2) >> 2; |
|
|
|
|
t1 = (bayer[1] + bayer[bayer_step] + |
|
|
|
|
bayer[bayer_step+2] + bayer[bayer_step*2+1]+2) >> 2; |
|
|
|
|
dst[-blue] = (uchar)t0; |
|
|
|
|
dst[0] = (uchar)t1; |
|
|
|
|
dst[-blue] = (T)t0; |
|
|
|
|
dst[0] = (T)t1; |
|
|
|
|
dst[blue] = bayer[bayer_step+1]; |
|
|
|
|
bayer++; |
|
|
|
|
dst += 3; |
|
|
|
@ -2052,7 +2095,7 @@ static void Bayer2RGB_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
size = dstmat.size(); |
|
|
|
|
dst0 = dstmat.data; |
|
|
|
|
dst0 = (T*)dstmat.data; |
|
|
|
|
if( size.height > 2 ) |
|
|
|
|
for( int i = 0; i < size.width*3; i++ ) |
|
|
|
|
{ |
|
|
|
@ -2083,7 +2126,7 @@ static void Bayer2RGB_VNG_8u( const Mat& srcmat, Mat& dstmat, int code ) |
|
|
|
|
// for too small images use the simple interpolation algorithm
|
|
|
|
|
if( MIN(size.width, size.height) < 8 ) |
|
|
|
|
{ |
|
|
|
|
Bayer2RGB_8u( srcmat, dstmat, code ); |
|
|
|
|
Bayer2RGB_<uchar, SIMDBayerInterpolator_8u>( srcmat, dstmat, code ); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -2912,27 +2955,42 @@ void cv::cvtColor( const InputArray& _src, OutputArray _dst, int code, int dcn ) |
|
|
|
|
|
|
|
|
|
case CV_BayerBG2GRAY: case CV_BayerGB2GRAY: case CV_BayerRG2GRAY: case CV_BayerGR2GRAY: |
|
|
|
|
if(dcn <= 0) dcn = 1; |
|
|
|
|
CV_Assert( scn == 1 && dcn == 1 && depth == CV_8U ); |
|
|
|
|
CV_Assert( scn == 1 && dcn == 1 ); |
|
|
|
|
|
|
|
|
|
_dst.create(sz, depth); |
|
|
|
|
dst = _dst.getMat(); |
|
|
|
|
|
|
|
|
|
Bayer2Gray_8u(src, dst, code); |
|
|
|
|
break;
|
|
|
|
|
if( depth == CV_8U ) |
|
|
|
|
Bayer2Gray_<uchar, SIMDBayerInterpolator_8u>(src, dst, code); |
|
|
|
|
else if( depth == CV_16U ) |
|
|
|
|
Bayer2Gray_<ushort, SIMDBayerStubInterpolator_<ushort> >(src, dst, code); |
|
|
|
|
else |
|
|
|
|
CV_Error(CV_StsUnsupportedFormat, "Bayer->Gray demosaicing only supports 8u and 16u types"); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case CV_BayerBG2BGR: case CV_BayerGB2BGR: case CV_BayerRG2BGR: case CV_BayerGR2BGR: |
|
|
|
|
case CV_BayerBG2BGR_VNG: case CV_BayerGB2BGR_VNG: case CV_BayerRG2BGR_VNG: case CV_BayerGR2BGR_VNG: |
|
|
|
|
if(dcn <= 0) dcn = 3; |
|
|
|
|
CV_Assert( scn == 1 && dcn == 3 && depth == CV_8U ); |
|
|
|
|
CV_Assert( scn == 1 && dcn == 3 ); |
|
|
|
|
|
|
|
|
|
_dst.create(sz, CV_MAKETYPE(depth, dcn)); |
|
|
|
|
dst = _dst.getMat(); |
|
|
|
|
|
|
|
|
|
if( code == CV_BayerBG2BGR || code == CV_BayerGB2BGR || |
|
|
|
|
code == CV_BayerRG2BGR || code == CV_BayerGR2BGR ) |
|
|
|
|
Bayer2RGB_8u(src, dst, code); |
|
|
|
|
{ |
|
|
|
|
if( depth == CV_8U ) |
|
|
|
|
Bayer2RGB_<uchar, SIMDBayerInterpolator_8u>(src, dst, code); |
|
|
|
|
else if( depth == CV_16U ) |
|
|
|
|
Bayer2RGB_<ushort, SIMDBayerStubInterpolator_<ushort> >(src, dst, code); |
|
|
|
|
else |
|
|
|
|
CV_Error(CV_StsUnsupportedFormat, "Bayer->RGB demosaicing only supports 8u and 16u types"); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
CV_Assert( depth == CV_8U ); |
|
|
|
|
Bayer2RGB_VNG_8u(src, dst, code); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); |
|
|
|
|