YUV格式和RGB格式互转

对于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: VS

cbuffer 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 DirectX
	outStruct.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 V
	float3 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 Y
	uint 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;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值