I found a section on the InternetCode, Can work, but the color is wrong, the red turns blue, the yellow turns blue, there is 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;
}