From: Daniil Osokin Date: Sun, 24 Feb 2013 17:50:08 +0000 (+0400) Subject: Added implementation for RGB to YUV420p color conversion X-Git-Tag: accepted/2.0/20130307.220821~10^2~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7255ede3af7bf3dcc0db841103d1e2e3b3a790d7;p=profile%2Fivi%2Fopencv.git Added implementation for RGB to YUV420p color conversion --- diff --git a/modules/imgproc/include/opencv2/imgproc/types_c.h b/modules/imgproc/include/opencv2/imgproc/types_c.h index 0e4f0a2..ba25af9 100644 --- a/modules/imgproc/include/opencv2/imgproc/types_c.h +++ b/modules/imgproc/include/opencv2/imgproc/types_c.h @@ -309,8 +309,22 @@ enum // alpha premultiplication CV_RGBA2mRGBA = 125, CV_mRGBA2RGBA = 126, - - CV_COLORCVT_MAX = 127 + + CV_RGB2YUV_I420 = 127, + CV_BGR2YUV_I420 = 128, + CV_RGB2YUV_IYUV = CV_RGB2YUV_I420, + CV_BGR2YUV_IYUV = CV_BGR2YUV_I420, + + CV_RGBA2YUV_I420 = 129, + CV_BGRA2YUV_I420 = 130, + CV_RGBA2YUV_IYUV = CV_RGBA2YUV_I420, + CV_BGRA2YUV_IYUV = CV_BGRA2YUV_I420, + CV_RGB2YUV_YV12 = 131, + CV_BGR2YUV_YV12 = 132, + CV_RGBA2YUV_YV12 = 133, + CV_BGRA2YUV_YV12 = 134, + + CV_COLORCVT_MAX = 135 }; diff --git a/modules/imgproc/src/color.cpp b/modules/imgproc/src/color.cpp index e85acea..82c2195 100644 --- a/modules/imgproc/src/color.cpp +++ b/modules/imgproc/src/color.cpp @@ -3076,6 +3076,58 @@ inline void cvtYUV420p2RGBA(Mat& _dst, int _stride, const uchar* _y1, const ucha converter(BlockedRange(0, _dst.rows/2)); } +///////////////////////////////////// RGB -> YUV420p ///////////////////////////////////// + +template +static void cvtRGBtoYUV420p(const Mat& src, Mat& dst) +{ + //const float coeffs[] = { 0.257f, 0.504f, 0.098f, + // -0.148f, -0.291f, 0.439f, + // -0.368f, -0.071f }; + const int coeffs[] = { 269484, 528482, 102760, + -155188, -305135, 460324, + -385875, -74448 }; + + const int w = src.cols; + const int h = src.rows; + + const int cn = src.channels(); + for( int i = 0; i < h / 2; i++ ) + { + const uchar* row0 = src.ptr(2*i); + const uchar* row1 = src.ptr(2*i + 1); + + uchar* y = dst.ptr(2*i); + uchar* u = dst.ptr(h + i/2) + (i % 2) * (w/2); + uchar* v = dst.ptr(h + (i + h/2)/2) + ((i + h/2) % 2) * (w/2); + if( uIdx == 2 ) std::swap(u, v); + + for( int j = 0, k = 0; j < w * cn; j += 2*cn, k++ ) + { + int r00 = row0[2-bIdx + j]; int g00 = row0[1 + j]; int b00 = row0[bIdx + j]; + int r01 = row0[2-bIdx + cn + j]; int g01 = row0[1 + cn + j]; int b01 = row0[bIdx + cn + j]; + int r10 = row1[2-bIdx + j]; int g10 = row1[1 + j]; int b10 = row1[bIdx + j]; + int r11 = row1[2-bIdx + cn + j]; int g11 = row1[1 + cn + j]; int b11 = row1[bIdx + cn + j]; + + int y00 = coeffs[0]*r00 + coeffs[1]*g00 + coeffs[2]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); + int y01 = coeffs[0]*r01 + coeffs[1]*g01 + coeffs[2]*b01 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); + int y10 = coeffs[0]*r10 + coeffs[1]*g10 + coeffs[2]*b10 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); + int y11 = coeffs[0]*r11 + coeffs[1]*g11 + coeffs[2]*b11 + (1 << (ITUR_BT_601_SHIFT - 1)) + (16 << ITUR_BT_601_SHIFT); + + y[2*k + 0] = saturate_cast(y00 >> ITUR_BT_601_SHIFT); + y[2*k + 1] = saturate_cast(y01 >> ITUR_BT_601_SHIFT); + y[2*k + dst.step + 0] = saturate_cast(y10 >> ITUR_BT_601_SHIFT); + y[2*k + dst.step + 1] = saturate_cast(y11 >> ITUR_BT_601_SHIFT); + + int u00 = coeffs[3]*r00 + coeffs[4]*g00 + coeffs[5]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (128 << ITUR_BT_601_SHIFT); + int v00 = coeffs[5]*r00 + coeffs[6]*g00 + coeffs[7]*b00 + (1 << (ITUR_BT_601_SHIFT - 1)) + (128 << ITUR_BT_601_SHIFT); + + u[k] = saturate_cast(u00 >> ITUR_BT_601_SHIFT); + v[k] = saturate_cast(v00 >> ITUR_BT_601_SHIFT); + } + } +} + ///////////////////////////////////// YUV422 -> RGB ///////////////////////////////////// template @@ -3713,6 +3765,31 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) src(Range(0, dstSz.height), Range::all()).copyTo(dst); } break; + case CV_RGB2YUV_YV12: case CV_BGR2YUV_YV12: case CV_RGBA2YUV_YV12: case CV_BGRA2YUV_YV12: + case CV_RGB2YUV_IYUV: case CV_BGR2YUV_IYUV: case CV_RGBA2YUV_IYUV: case CV_BGRA2YUV_IYUV: + { + if (dcn <= 0) dcn = 1; + const int bIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_BGR2YUV_YV12 || code == CV_BGRA2YUV_YV12) ? 0 : 2; + const int uIdx = (code == CV_BGR2YUV_IYUV || code == CV_BGRA2YUV_IYUV || code == CV_RGB2YUV_IYUV || code == CV_RGBA2YUV_IYUV) ? 1 : 2; + + CV_Assert( (scn == 3 || scn == 4) && depth == CV_8U ); + CV_Assert( dcn == 1 ); + CV_Assert( sz.width % 2 == 0 && sz.height % 2 == 0 ); + + Size dstSz(sz.width, sz.height / 2 * 3); + _dst.create(dstSz, CV_MAKETYPE(depth, dcn)); + dst = _dst.getMat(); + + switch(bIdx + uIdx*10) + { + case 10: cvtRGBtoYUV420p<0, 1>(src, dst); break; + case 12: cvtRGBtoYUV420p<2, 1>(src, dst); break; + case 20: cvtRGBtoYUV420p<0, 2>(src, dst); break; + case 22: cvtRGBtoYUV420p<2, 2>(src, dst); break; + default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); break; + }; + } + break; case CV_YUV2RGB_UYVY: case CV_YUV2BGR_UYVY: case CV_YUV2RGBA_UYVY: case CV_YUV2BGRA_UYVY: case CV_YUV2RGB_YUY2: case CV_YUV2BGR_YUY2: case CV_YUV2RGB_YVYU: case CV_YUV2BGR_YVYU: case CV_YUV2RGBA_YUY2: case CV_YUV2BGRA_YUY2: case CV_YUV2RGBA_YVYU: case CV_YUV2BGRA_YVYU: @@ -3795,7 +3872,7 @@ void cv::cvtColor( InputArray _src, OutputArray _dst, int code, int dcn ) CV_Error( CV_StsBadArg, "Unsupported image depth" ); } } - break; + break; default: CV_Error( CV_StsBadFlag, "Unknown/unsupported color conversion code" ); }