Http://real.zdell.com/a/200512/818.html
I found a piece of code on the Internet that can work, but the color is incorrect. The red color turns blue, the yellow color turns blue, and I have time to look for problems.
This problem has been confusing for a long time when I was a beginner in DirectX. I posted it to provide a reference for beginners.
# Include "ddraw. H"
# Pragma comment (Lib, "ddraw. lib ")
# Define file_height 288
# Define file_width 352
# Define draw_top 0
# Define draw_left 0
# Define draw_height 288
# Define fig 352
Bool drawyv12 (hwnd)
{
Lpdirectdraw lpdd; // DirectDraw object pointer
Lpdirectdrawsurface lpddsprimary; // DirectDraw Master surface pointer
Lpdirectdrawsurface lpddsoffscr; // DirectDraw off-screen surface pointer
Ddsurfacedesc ddsd; // DirectDraw surface description
Rect rctdest; // target region
Rect rctsour; // Source Region
Hresult ddrval; // return value of the DirectDraw Function
// Create a directcraw object
If (directdrawcreate (null, & lpdd, null )! = Dd_ OK)
Return false;
// Set the collaboration Layer
If (lpdd-> setcooperativelevel (hwnd,
Ddscl_normal | ddscl_nowindowchanges )! = Dd_ OK)
Return false;
// Create the primary surface
Zeromemory (& ddsd, sizeof (ddsd ));
Ddsd. dwsize = sizeof (ddsd );
Ddsd. dwflags = ddsd_caps;
Ddsd. ddscaps. dwcaps = ddscaps_primarysurface;
If (lpdd-> createsurface (& ddsd, & lpddsprimary, null )! = Dd_ OK)
Return false;
// Create an off-screen surface object
Zeromemory (& ddsd, sizeof (ddsd ));
Ddsd. dwsize = sizeof (ddsd );
Ddsd. ddscaps. dwcaps = ddscaps_offscreenplain | ddscaps_videomemory; // ddscaps_overlay
Ddscaps_offscreenplain;
Ddsd. dwflags = ddsd_caps | ddsd_height | ddsd_width | ddsd_pixelformat;
Ddsd. dwwidth = draw_widht;
Ddsd. dwheight = draw_height;
Ddsd. ddpfpixelformat. dwsize = sizeof (ddpixelformat );
Ddsd. ddpfpixelformat. dwflags = ddpf_fourcc | ddpf_yuv;
Ddsd. ddpfpixelformat. dwfourcc = makefourcc ('y', 'V', '1', '2 ');
Ddsd. ddpfpixelformat. dwyuvbitcount = 8;
If (lpdd-> createsurface (& ddsd, & lpddsoffscr, null )! = Dd_ OK)
Return false;
// Load the yv12 Image File
File * f = fopen ("test. yv12", "rb ");
Lpbyte lpyv12 = new byte [file_width * file_height * 3/2];
Uint ilen = fread (lpyv12, 1, file_width * file_height * 3/2, F );
Fclose (f );
Lpbyte lpy = lpyv12;
Lpbyte LPV = lpyv12 + file_width * file_height;
Lpbyte LPU = lpyv12 + file_width * file_height * 5/4;
Ddrval = lpddsoffscr-> lock (null, & ddsd, ddlock_wait | ddlock_writeonly, null );
While (ddrval = dderr_wasstilldrawing );
If (ddrval! = Dd_ OK)
Return false;
Lpbyte lpsurf = (lpbyte) ddsd. lpsurface;
Lpbyte lpy1 = lpsurf;
Lpbyte lpv1 = lpsurf + ddsd. lpitch * file_height;
Lpbyte lpu1 = lpv1 + ddsd. lpitch * file_height/4;
Int noffset = draw_top * file_width + draw_left;
// Fill the off-screen surface
If (lpsurf)
{
Int I = 0;
// Fill y Data
Lpy + = noffset;
For (I = 0; I <ddsd. dwheight; I ++)
{
Memcpy (lpsurf, lpy, ddsd. dwwidth );
Lpy + = file_width;
Lpsurf + = ddsd. lpitch;
}
// Fill v Data
LPV + = draw_top * file_width/4 + draw_left/2;
For (I = 0; I <ddsd. dwheight/2; I ++)
{
Memcpy (lpsurf, LPV, ddsd. dwwidth/2 );
LPV + = file_width/2;
Lpsurf + = ddsd. lpitch/2;
}
// Fill u Data
LPU + = draw_top * file_width/4 + draw_left/2;
For (I = 0; I <ddsd. dwheight/2; I ++)
{
Memcpy (lpsurf, LPU, ddsd. dwwidth/2 );
LPU + = file_width/2;
Lpsurf + = ddsd. lpitch/2;
}
}
Lpddsoffscr-> unlock (null );
Delete lpyv12;
// BLT to the main surface
Rctsour. Left = 0;
Rctsour. Top = 0;
Rctsour. Right = ddsd. dwwidth;
Rctsour. Bottom = ddsd. dwheight;
Getclientrect (hwnd, & rctdest );
Clienttoscreen (hwnd, (lppoint) & rctdest. Left );
Clienttoscreen (hwnd, (lppoint) & rctdest. Right );
Ddrval = lpddsprimary-> BLT (& rctdest, lpddsoffscr, & rctsour, ddblt_wait, null );
While (ddrval = dderr_wasstilldrawing );
If (ddrval! = Dd_ OK)
Return false;
// Release the DirectDraw object
If (lpdd! = NULL)
{
If (lpddsprimary! = NULL)
{
Lpddsprimary-> release ();
Lpddsprimary = NULL;
}
If (lpddsoffscr! = NULL)
{
Lpddsoffscr-> release ();
Lpddsoffscr = NULL;
}
Lpdd-> release ();
Lpdd = NULL;
}
Return true;
}