diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index df2ee31931..b95286bf1a 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -819,16 +819,18 @@ template struct RGB2YCrCb_f { typedef _Tp channel_type; - RGB2YCrCb_f(int _srccn, int _blueIdx, const float* _coeffs) : srccn(_srccn), blueIdx(_blueIdx) + RGB2YCrCb_f(int _srccn, int _blueIdx, bool _isCrCb) : srccn(_srccn), blueIdx(_blueIdx), isCrCb(_isCrCb) { - static const float coeffs0[] = {R2YF, G2YF, B2YF, YCRF, YCBF}; - memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0])); + static const float coeffs_crb[] = { R2YF, G2YF, B2YF, YCRF, YCBF }; + static const float coeffs_yuv[] = { R2YF, G2YF, B2YF, R2VF, B2UF }; + memcpy(coeffs, isCrCb ? coeffs_crb : coeffs_yuv, 5*sizeof(coeffs[0])); if(blueIdx==0) std::swap(coeffs[0], coeffs[2]); } void operator()(const _Tp* src, _Tp* dst, int n) const { int scn = srccn, bidx = blueIdx; + int yuvOrder = !isCrCb; //1 if YUV, 0 if YCrCb const _Tp delta = ColorChannel<_Tp>::half(); float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4]; n *= 3; @@ -837,10 +839,11 @@ template struct RGB2YCrCb_f _Tp Y = saturate_cast<_Tp>(src[0]*C0 + src[1]*C1 + src[2]*C2); _Tp Cr = saturate_cast<_Tp>((src[bidx^2] - Y)*C3 + delta); _Tp Cb = saturate_cast<_Tp>((src[bidx] - Y)*C4 + delta); - dst[i] = Y; dst[i+1] = Cr; dst[i+2] = Cb; + dst[i] = Y; dst[i+1+yuvOrder] = Cr; dst[i+2-yuvOrder] = Cb; } } int srccn, blueIdx; + bool isCrCb; float coeffs[5]; }; @@ -849,16 +852,18 @@ template struct RGB2YCrCb_i { typedef _Tp channel_type; - RGB2YCrCb_i(int _srccn, int _blueIdx, const int* _coeffs) - : srccn(_srccn), blueIdx(_blueIdx) + RGB2YCrCb_i(int _srccn, int _blueIdx, bool _isCrCb) + : srccn(_srccn), blueIdx(_blueIdx), isCrCb(_isCrCb) { - static const int coeffs0[] = {R2Y, G2Y, B2Y, YCRI, YCBI}; - memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 5*sizeof(coeffs[0])); + static const int coeffs_crb[] = { R2Y, G2Y, B2Y, YCRI, YCBI }; + static const int coeffs_yuv[] = { R2Y, G2Y, B2Y, R2VI, B2UI }; + memcpy(coeffs, isCrCb ? coeffs_crb : coeffs_yuv, 5*sizeof(coeffs[0])); if(blueIdx==0) std::swap(coeffs[0], coeffs[2]); } void operator()(const _Tp* src, _Tp* dst, int n) const { int scn = srccn, bidx = blueIdx; + int yuvOrder = !isCrCb; //1 if YUV, 0 if YCrCb int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3], C4 = coeffs[4]; int delta = ColorChannel<_Tp>::half()*(1 << yuv_shift); n *= 3; @@ -868,11 +873,12 @@ template struct RGB2YCrCb_i int Cr = CV_DESCALE((src[bidx^2] - Y)*C3 + delta, yuv_shift); int Cb = CV_DESCALE((src[bidx] - Y)*C4 + delta, yuv_shift); dst[i] = saturate_cast<_Tp>(Y); - dst[i+1] = saturate_cast<_Tp>(Cr); - dst[i+2] = saturate_cast<_Tp>(Cb); + dst[i+1+yuvOrder] = saturate_cast<_Tp>(Cr); + dst[i+2-yuvOrder] = saturate_cast<_Tp>(Cb); } } int srccn, blueIdx; + bool isCrCb; int coeffs[5]; }; @@ -881,23 +887,25 @@ template struct YCrCb2RGB_f { typedef _Tp channel_type; - YCrCb2RGB_f(int _dstcn, int _blueIdx, const float* _coeffs) - : dstcn(_dstcn), blueIdx(_blueIdx) + YCrCb2RGB_f(int _dstcn, int _blueIdx, bool _isCrCb) + : dstcn(_dstcn), blueIdx(_blueIdx), isCrCb(_isCrCb) { - static const float coeffs0[] = {CR2RF, CR2GF, CB2GF, CB2BF}; - memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0])); + static const float coeffs_cbr[] = {CR2RF, CR2GF, CB2GF, CB2BF}; + static const float coeffs_yuv[] = { V2RF, V2GF, U2GF, U2BF}; + memcpy(coeffs, isCrCb ? coeffs_cbr : coeffs_yuv, 4*sizeof(coeffs[0])); } void operator()(const _Tp* src, _Tp* dst, int n) const { int dcn = dstcn, bidx = blueIdx; + int yuvOrder = !isCrCb; //1 if YUV, 0 if YCrCb const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max(); float C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3]; n *= 3; for(int i = 0; i < n; i += 3, dst += dcn) { _Tp Y = src[i]; - _Tp Cr = src[i+1]; - _Tp Cb = src[i+2]; + _Tp Cr = src[i+1+yuvOrder]; + _Tp Cb = src[i+2-yuvOrder]; _Tp b = saturate_cast<_Tp>(Y + (Cb - delta)*C3); _Tp g = saturate_cast<_Tp>(Y + (Cb - delta)*C2 + (Cr - delta)*C1); @@ -909,6 +917,7 @@ template struct YCrCb2RGB_f } } int dstcn, blueIdx; + bool isCrCb; float coeffs[4]; }; @@ -917,24 +926,26 @@ template struct YCrCb2RGB_i { typedef _Tp channel_type; - YCrCb2RGB_i(int _dstcn, int _blueIdx, const int* _coeffs) - : dstcn(_dstcn), blueIdx(_blueIdx) + YCrCb2RGB_i(int _dstcn, int _blueIdx, bool _isCrCb) + : dstcn(_dstcn), blueIdx(_blueIdx), isCrCb(_isCrCb) { - static const int coeffs0[] = {CR2RI, CR2GI, CB2GI, CB2BI}; - memcpy(coeffs, _coeffs ? _coeffs : coeffs0, 4*sizeof(coeffs[0])); + static const int coeffs_crb[] = { CR2RI, CR2GI, CB2GI, CB2BI}; + static const int coeffs_yuv[] = { V2RI, V2GI, U2GI, U2BI }; + memcpy(coeffs, isCrCb ? coeffs_crb : coeffs_yuv, 4*sizeof(coeffs[0])); } void operator()(const _Tp* src, _Tp* dst, int n) const { int dcn = dstcn, bidx = blueIdx; + int yuvOrder = !isCrCb; //1 if YUV, 0 if YCrCb const _Tp delta = ColorChannel<_Tp>::half(), alpha = ColorChannel<_Tp>::max(); int C0 = coeffs[0], C1 = coeffs[1], C2 = coeffs[2], C3 = coeffs[3]; n *= 3; for(int i = 0; i < n; i += 3, dst += dcn) { _Tp Y = src[i]; - _Tp Cr = src[i+1]; - _Tp Cb = src[i+2]; + _Tp Cr = src[i+1+yuvOrder]; + _Tp Cb = src[i+2-yuvOrder]; int b = Y + CV_DESCALE((Cb - delta)*C3, yuv_shift); int g = Y + CV_DESCALE((Cb - delta)*C2 + (Cr - delta)*C1, yuv_shift); @@ -948,6 +959,7 @@ template struct YCrCb2RGB_i } } int dstcn, blueIdx; + bool isCrCb; int coeffs[4]; }; @@ -3864,10 +3876,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) { CV_Assert( scn == 3 || scn == 4 ); bidx = code == CV_BGR2YCrCb || code == CV_BGR2YUV ? 0 : 2; - static const float yuv_f[] = { R2YF, G2YF, B2YF, R2VF, B2UF }; - static const int yuv_i[] = { R2Y, G2Y, B2Y, R2VI, B2UI }; - const float* coeffs_f = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_f; - const int* coeffs_i = code == CV_BGR2YCrCb || code == CV_RGB2YCrCb ? 0 : yuv_i; + const bool isCrCb = (code == CV_BGR2YCrCb || code == CV_RGB2YCrCb); _dst.create(sz, CV_MAKETYPE(depth, 3)); dst = _dst.getMat(); @@ -3878,12 +3887,12 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) if((code == CV_RGB2YCrCb || code == CV_BGR2YCrCb) && tegra::cvtRGB2YCrCb(src, dst, bidx)) break; #endif - CvtColorLoop(src, dst, RGB2YCrCb_i(scn, bidx, coeffs_i)); + CvtColorLoop(src, dst, RGB2YCrCb_i(scn, bidx, isCrCb)); } else if( depth == CV_16U ) - CvtColorLoop(src, dst, RGB2YCrCb_i(scn, bidx, coeffs_i)); + CvtColorLoop(src, dst, RGB2YCrCb_i(scn, bidx, isCrCb)); else - CvtColorLoop(src, dst, RGB2YCrCb_f(scn, bidx, coeffs_f)); + CvtColorLoop(src, dst, RGB2YCrCb_f(scn, bidx, isCrCb)); } break; @@ -3893,20 +3902,17 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) if( dcn <= 0 ) dcn = 3; CV_Assert( scn == 3 && (dcn == 3 || dcn == 4) ); bidx = code == CV_YCrCb2BGR || code == CV_YUV2BGR ? 0 : 2; - static const float yuv_f[] = {V2RF, V2GF, U2GF, U2BF}; - static const int yuv_i[] = { V2RI, V2GI, U2GI, U2BI }; - const float* coeffs_f = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_f; - const int* coeffs_i = code == CV_YCrCb2BGR || code == CV_YCrCb2RGB ? 0 : yuv_i; + const bool isCrCb = (code == CV_YCrCb2BGR || code == CV_YCrCb2RGB); _dst.create(sz, CV_MAKETYPE(depth, dcn)); dst = _dst.getMat(); if( depth == CV_8U ) - CvtColorLoop(src, dst, YCrCb2RGB_i(dcn, bidx, coeffs_i)); + CvtColorLoop(src, dst, YCrCb2RGB_i(dcn, bidx, isCrCb)); else if( depth == CV_16U ) - CvtColorLoop(src, dst, YCrCb2RGB_i(dcn, bidx, coeffs_i)); + CvtColorLoop(src, dst, YCrCb2RGB_i(dcn, bidx, isCrCb)); else - CvtColorLoop(src, dst, YCrCb2RGB_f(dcn, bidx, coeffs_f)); + CvtColorLoop(src, dst, YCrCb2RGB_f(dcn, bidx, isCrCb)); } break; diff --git a/modules/ocl/src/opencl/cvt_color.cl b/modules/ocl/src/opencl/cvt_color.cl index 41b4232eb7..31b62744b9 100644 --- a/modules/ocl/src/opencl/cvt_color.cl +++ b/modules/ocl/src/opencl/cvt_color.cl @@ -295,8 +295,8 @@ __kernel void RGB2YUV(int cols, int rows, int src_step, int dst_step, #endif dst_ptr[0] = SAT_CAST( Y ); - dst_ptr[1] = SAT_CAST( V ); //sic! store channels as YVU, not YUV - dst_ptr[2] = SAT_CAST( U ); + dst_ptr[1] = SAT_CAST( U ); + dst_ptr[2] = SAT_CAST( V ); } #elif (2 == pixels_per_work_item) { @@ -323,8 +323,7 @@ __kernel void RGB2YUV(int cols, int rows, int src_step, int dst_step, const VECTOR2 U = SAT_CAST2(ui); const VECTOR2 V = SAT_CAST2(vi); #endif - //sic! store channels as YVU, not YUV - vstore8((VECTOR8)(Y.s0, V.s0, U.s0, 0, Y.s1, V.s1, U.s1, 0), 0, dst_ptr); + vstore8((VECTOR8)(Y.s0, U.s0, V.s0, 0, Y.s1, U.s1, V.s1, 0), 0, dst_ptr); } #elif (4 == pixels_per_work_item) { @@ -342,8 +341,7 @@ __kernel void RGB2YUV(int cols, int rows, int src_step, int dst_step, const VECTOR4 Y = SAT_CAST4(yi); const VECTOR4 U = SAT_CAST4(ui); const VECTOR4 V = SAT_CAST4(vi); - //sic! store channels as YVU, not YUV - vstore16((VECTOR16)(Y.s0, V.s0, U.s0, 0, Y.s1, V.s1, U.s1, 0, Y.s2, V.s2, U.s2, 0, Y.s3, V.s3, U.s3, 0), 0, dst_ptr); + vstore16((VECTOR16)(Y.s0, U.s0, V.s0, 0, Y.s1, U.s1, V.s1, 0, Y.s2, U.s2, V.s2, 0, Y.s3, U.s3, V.s3, 0), 0, dst_ptr); #endif } #endif //pixels_per_work_item @@ -377,8 +375,7 @@ __kernel void YUV2RGB(int cols, int rows, int src_step, int dst_step, #if (1 == pixels_per_work_item) { - //sic! channels stored as YVU, not YUV - const DATA_TYPE yuv[] = {src_ptr[0], src_ptr[2], src_ptr[1]}; + const DATA_TYPE yuv[] = {src_ptr[0], src_ptr[1], src_ptr[2]}; #ifdef DEPTH_5 float B = yuv[0] + (yuv[1] - HALF_MAX) * coeffs[0]; @@ -402,19 +399,17 @@ __kernel void YUV2RGB(int cols, int rows, int src_step, int dst_step, const VECTOR8 r0 = vload8(0, src_ptr); #ifdef DEPTH_5 - //sic! channels stored as YVU, not YUV const float2 Y = r0.s04; - const float2 U = r0.s26; - const float2 V = r0.s15; + const float2 U = r0.s15; + const float2 V = r0.s26; const float2 c0 = (bidx != 0) ? (Y + (V - HALF_MAX) * coeffs[3]) : (Y + (U - HALF_MAX) * coeffs[0]); const float2 c1 = Y + (V - HALF_MAX) * coeffs[2] + (U - HALF_MAX) * coeffs[1]; const float2 c2 = (bidx != 0) ? (Y + (U - HALF_MAX) * coeffs[0]) : (Y + (V - HALF_MAX) * coeffs[3]); #else - //sic! channels stored as YVU, not YUV const int2 Y = convert_int2(r0.s04); - const int2 U = convert_int2(r0.s26); - const int2 V = convert_int2(r0.s15); + const int2 U = convert_int2(r0.s15); + const int2 V = convert_int2(r0.s26); const int2 c0i = (bidx != 0) ? (Y + CV_DESCALE((V - HALF_MAX) * coeffs[3], yuv_shift)) : (Y + CV_DESCALE((U - HALF_MAX) * coeffs[0], yuv_shift)); const int2 c1i = Y + CV_DESCALE((V - HALF_MAX) * coeffs[2] + (U - HALF_MAX) * coeffs[1], yuv_shift); @@ -436,10 +431,9 @@ __kernel void YUV2RGB(int cols, int rows, int src_step, int dst_step, #ifndef DEPTH_5 const VECTOR16 r0 = vload16(0, src_ptr); - //sic! channels stored as YVU, not YUV const int4 Y = convert_int4(r0.s048c); - const int4 U = convert_int4(r0.s26ae); - const int4 V = convert_int4(r0.s159d); + const int4 U = convert_int4(r0.s159d); + const int4 V = convert_int4(r0.s26ae); const int4 c0i = (bidx != 0) ? (Y + CV_DESCALE((V - HALF_MAX) * coeffs[3], yuv_shift)) : (Y + CV_DESCALE((U - HALF_MAX) * coeffs[0], yuv_shift)); const int4 c1i = Y + CV_DESCALE((V - HALF_MAX) * coeffs[2] + (U - HALF_MAX) * coeffs[1], yuv_shift);