YUV格式和RGB格式互转

来源:互联网 发布:淘宝捷易通是真的吗 编辑:程序博客网 时间:2024/06/05 05:41

对于R8G8B8A8格式的颜色,可以通过下面公式转换为YUV(I420)格式。

unsigned char Y = static_cast<unsigned char>((65.738*r + 129.057*g + 25.064*b)/256 + 16);

unsigned char U = static_cast<unsigned char>((-37.945*r - 74.494*g + 112.439*b)/256 + 128);

unsigned char V = static_cast<unsigned char>((112.439*r - 94.154*g - 18.285*b)/256 + 128);

如果是浮点型(r,g,b,a @[0, 1])使用类似的方法,具体参考下面网站。

Wiki: http://zh.wikipedia.org/wiki/YUV

YUV(I420): http://www.fourcc.org/yuv.php#IYUV


同时可以使用GPU实现此算法,以下为DX10的一段shader实现GPU的RGBA8到YUV的转化。

准备工作:使用贴图为RGB颜色空间普通颜色贴图格式,三个render target, Y(rgba8,存放四个Y值), U(r8,存放一个U值), V(r8,存放一个V值)。render target的尺寸为原来贴图的width/2, height/2。

// PSENTRY: PS// VSENTRY: VScbuffer constantsVS : register(b0){float4 gv_renderColor;float4 gv_rectangle;// xy=source texture size, zw=destination size};const static float2 quadCorners[4] = { float2(0, 0), float2(1, 0), float2(0, 1), float2(1, 1) };Texture2D mapColor : register(t0);sampler mapColorSampler : register(s0);struct VS_OUTPUT{    float4 pos: SV_Position;float2 tex                  : TexCoord;};VS_OUTPUT VS(uint vID : SV_VertexID){VS_OUTPUT outStruct;outStruct.pos = float4(float2(-1,-1) + quadCorners[vID] * 2, 0, 1);outStruct.pos.y = -outStruct.pos.y;// NCD y axis is reversed in DirectXoutStruct.tex = quadCorners[vID];return outStruct;}struct PS_OUTPUT{float4 y4: SV_Target0;float  u  : SV_Target1;float  v  : SV_Target2;};float CalcY( uint pid, uint w, uint h ) { float2 uv = float2( (float)(pid%(w))/w, (float)(pid/(w))/h );float3 rgb = mapColor.SampleLevel( mapColorSampler, uv, 0).rgb;return ((65.738*rgb.x + 129.057*rgb.y + 25.064*rgb.z) + 16)/256;   }PS_OUTPUT PS( VS_OUTPUT IN ){    PS_OUTPUT outStruct;// calc U Vfloat3 rgb = mapColor.SampleLevel( mapColorSampler, IN.tex, 0).rgb;outStruct.u = ((-37.945*rgb.x - 74.494*rgb.y + 112.439*rgb.z) + 128)/256;outStruct.v = ((112.439*rgb.x - 94.154*rgb.y - 18.285*rgb.z) + 128)/256;// calc Yuint half_width = (uint)(gv_rectangle.z);uint half_height = (uint)(gv_rectangle.w);uint cur_x = (uint)(IN.tex.x*gv_rectangle.z);uint cur_y = (uint)(IN.tex.y*gv_rectangle.w);uint pid = 4*(cur_y*half_width + cur_x);outStruct.y4 = float4(CalcY(pid, 2*half_width, 2*half_height),     CalcY(pid+1, 2*half_width, 2*half_height),     CalcY(pid+2, 2*half_width, 2*half_height), CalcY(pid+3, 2*half_width, 2*half_height));return outStruct;}


原创粉丝点击