[Theora-dev] yuv2rgb

Daniel Vogel Daniel.Vogel at epicgames.com
Thu Dec 9 18:38:32 PST 2004


The attached snippet is what I use to convert from Theora's YUV to D3D's
UYVY or ARGB.

The formatting got slightly munged during the copy & pase.

-- Daniel, Epic Games Inc.  

> -----Original Message-----
> From: theora-dev-bounces at xiph.org 
> [mailto:theora-dev-bounces at xiph.org] On Behalf Of lluis
> Sent: Wednesday, December 08, 2004 7:30 PM
> To: theora-dev at xiph.org
> Subject: [Theora-dev] yuv2rgb
> 
> 
> hi all,
> 
> i'm trying to code a tool to get some images from a 
> ogg/theora file ....
> 
> so basically i need to get a frame and convert to rgb ... and 
> here is my
> question (sorry, i'm newbe here) ...
> 
> how to convert a yuv_buffer to a rgb matrix ?
> 
> i tryied diferent ways but my mistakes are bassically cause i don't
>  understant how yuv_buffer structure works ...
> 
> anybody can help? thanks a lot.
> 
> ll-.
> _______________________________________________
> Theora-dev mailing list
> Theora-dev at xiph.org
> http://lists.xiph.org/mailman/listinfo/theora-dev
> 
-------------- next part --------------
	yuv_buffer YUVBuffer;
	theora_decode_YUVout( &TheoraDecoder, &YUVBuffer );

	DWORD	SizeX	= TheoraInfo.width,
			SizeY	= TheoraInfo.height;

	char*	SrcY	= YUVBuffer.y;
	char*	SrcU	= YUVBuffer.u;
	char*	SrcV	= YUVBuffer.v;

	check( YUVBuffer.y_width  == YUVBuffer.uv_width  * 2 );
	check( YUVBuffer.y_height == YUVBuffer.uv_height * 2 );
	check( YUVBuffer.y_width  == GetSizeX() );
	check( YUVBuffer.y_height == GetSizeY() );

	if( GPixelFormats[PF_UYVY].Supported )
	{
		//@todo optimization: Converts from planar YUV to interleaved PF_UYVY format.
		for( UINT y=0; y<SizeY; y++ )
		{
			for( UINT x=0; x<SizeX/2; x++ )
			{
				DWORD			OffsetY0	= YUVBuffer.y_stride  *  y    + x*2;
				DWORD			OffsetY1	= YUVBuffer.y_stride  *  y    + x*2 + 1;
				DWORD			OffsetUV	= YUVBuffer.uv_stride * (y/2) + x;

				unsigned char	Y0			= SrcY[OffsetY0];
				unsigned char   Y1			= SrcY[OffsetY1];
				unsigned char	U			= SrcU[OffsetUV];
				unsigned char	V			= SrcV[OffsetUV];

				((DWORD*)Dest)[y*(SizeX/2) + x] = (Y1 << 24) | (V << 16) | (Y0 << 8) | U;
			}
		}
	}
	else
	{
		FColor*	DestColor = (FColor*) Dest;

		//@todo optimization: Converts from planar YUV to interleaved ARGB. This codepath is currently hit with NVIDIA cards!
		for( UINT y=0; y<SizeY; y++ )
		{
			for( UINT x=0; x<SizeX/2; x++ )
			{
				DWORD			OffsetY0	= YUVBuffer.y_stride  *  y    + x*2;
				DWORD			OffsetY1	= YUVBuffer.y_stride  *  y    + x*2 + 1;
				DWORD			OffsetUV	= YUVBuffer.uv_stride * (y/2) + x;

				unsigned char	Y0			= SrcY[OffsetY0];
				unsigned char   Y1			= SrcY[OffsetY1];
				unsigned char	U			= SrcU[OffsetUV];
				unsigned char	V			= SrcV[OffsetUV];

				//@todo optimization: this is a prime candidate for SSE/ Altivec or fixed point integer or moving it to the GPU though we really ought to just avoid this codepath altogether.
				DestColor->R				= Clamp( appTrunc( Y0 + 1.402f * (V-128) ), 0, 255 );
				DestColor->G				= Clamp( appTrunc( Y0 - 0.34414f * (U-128) - 0.71414f * (V-128) ), 0, 255 );
				DestColor->B				= Clamp( appTrunc( Y0 + 1.772 * (U-128) ), 0, 255 );
				DestColor->A				= 255;
				DestColor++;

				//@todo optimization: this is a prime candidate for SSE/ Altivec or fixed point integer or moving it to the GPU though we really ought to just avoid this codepath altogether.
				DestColor->R				= Clamp( appTrunc( Y1 + 1.402f * (V-128) ), 0, 255 );
				DestColor->G				= Clamp( appTrunc( Y1 - 0.34414f * (U-128) - 0.71414f * (V-128) ), 0, 255 );
				DestColor->B				= Clamp( appTrunc( Y1 + 1.772 * (U-128) ), 0, 255 );
				DestColor->A				= 255;
				DestColor++;
			}
		}

	}


More information about the Theora-dev mailing list