2023年12月22日发(作者:)

#define WIN32_LEAN_AND_MEAN // 从 Windows 头中排除极少使用的资料

#include

#include

#include

#include

#include

#include

#include "ddraw.h"

#pragma comment(lib,"")

// 此代码模块中包含的函数的前向声明:

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

BOOL DrawYV12(HWND hWnd); // Draw YV12 图像

// 应用入口

int APIENTRY _tWinMain(HINSTANCE hInstance,

HINSTANCE hPrevInstance,

LPTSTR lpCmdLine,

int nCmdShow)

{

MSG msg;

WNDCLASSEX wcex;

TCHAR szWindowClass[] = "Draw YV12"; // 主窗口类名

HWND hWnd;

= sizeof(WNDCLASSEX);

= CS_HREDRAW | CS_VREDRAW;

dProc = (WNDPROC)WndProc;

xtra = 0;

xtra = 0;

nce = hInstance;

= NULL;

r = LoadCursor(NULL, IDC_ARROW);

kground = HBRUSH(COLOR_WINDOW + 1);

nuName = NULL;

assName = szWindowClass;

m = NULL;

RegisterClassEx(&wcex);

hWnd = CreateWindow(szWindowClass, szWindowClass,

// 窗口消息处理函

WS_OVERLAPPEDWINDOW,//WS_POPUP,

0, 0,

800,//GetSystemMetrics(SM_CXSCREEN),

600,//GetSystemMetrics(SM_CYSCREEN),

NULL, NULL, hInstance, NULL);

if (!hWnd)

{

return FALSE;

}

ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd);

// 主消息循环:

while (GetMessage(&msg, NULL, 0, 0))

{

TranslateMessage(&msg);

DispatchMessage(&msg);

}

return (int) ;

}

//

// 函数: WndProc(HWND, unsigned, WORD, LONG)

//

// 目的: 处理主窗口的消息。

//

// WM_COMMAND - 处理应用程序菜单

// WM_PAINT - 绘制主窗口

// WM_DESTROY - 发送退出消息并返回

//

//

LRESULT CALLBACK WndProc(HWND hWnd, UINT message,

RAM lParam)

{

switch (message)

{

case WM_KEYDOWN:

switch( wParam )

{

case VK_ESCAPE:

WPARAM wParam, LPA

case VK_F12:

PostMessage(hWnd, WM_CLOSE, 0, 0);

break;

case VK_TAB:

if(!DrawYV12(hWnd))

MessageBox(hWnd,"Draw yv12 image failed","DDraw error", MB_OK);

break;

}

case WM_DESTROY:

PostQuitMessage(0);

break;

default:

return DefWindowProc(hWnd, message, wParam, lParam);

}

return 0;

}

#define FILE_HEIGHT 288

#define FILE_WIDTH 352

#define DRAW_TOP 0

#define DRAW_LEFT 0

#define DRAW_HEIGHT 288

#define DRAW_WIDHT 352

BOOL DrawYV12(HWND hWnd)

{

LPDIRECTDRAW lpDD; // DirectDraw 对象指针

LPDIRECTDRAWSURFACE lpDDSPrimary; // DirectDraw 主表面指针

LPDIRECTDRAWSURFACE lpDDSOffScr; // DirectDraw 离屏表面指针

DDSURFACEDESC ddsd; // DirectDraw 表面描述

RECT rctDest; // 目标区域

RECT rctSour; // 源区域

HRESULT ddRval; // DirectDraw 函数返回值

// 创建DirectCraw对象

if (DirectDrawCreate(NULL, &lpDD, NULL) != DD_OK)

return FALSE;

// 设置协作层

if (lpDD->SetCooperativeLevel(hWnd,

DDSCL_NORMAL | DDSCL_NOWINDOWCHANGES) != DD_OK)

return FALSE;

// 创建主表面

ZeroMemory(&ddsd, sizeof(ddsd));

= sizeof(ddsd);

s = DDSD_CAPS;

= DDSCAPS_PRIMARYSURFACE;

if (lpDD->CreateSurface(&ddsd, &lpDDSPrimary, NULL) != DD_OK)

return FALSE;

// 创建离屏表面对象

ZeroMemory(&ddsd, sizeof(ddsd));

= sizeof(ddsd);

= DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY; //DDSCAPS_OVERLAY DDSCAPS_OFFSCREENPLAIN;

s = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;

h = DRAW_WIDHT;

ht = DRAW_HEIGHT;

= sizeof(DDPIXELFORMAT);

s = DDPF_FOURCC | DDPF_YUV ;

CC = MAKEFOURCC('Y','V','1','2');

itCount = 8;

if (lpDD->CreateSurface(&ddsd, &lpDDSOffScr, NULL) != DD_OK)

return FALSE;

// 加载yv12图像文件

FILE * f = fopen("12","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)ace;

LPBYTE lpY1 = lpSurf;

LPBYTE lpV1 = lpSurf + * FILE_HEIGHT;

LPBYTE lpU1 = lpV1 + * FILE_HEIGHT / 4;

int nOffset = DRAW_TOP*FILE_WIDTH+DRAW_LEFT;

// 填充离屏表面

if(lpSurf)

{

int i = 0;

// fill Y data

lpY += nOffset;

for(i=0; i

{

memcpy(lpSurf, lpY, h);

lpY += FILE_WIDTH;

lpSurf += ;

}

// fill V data

lpY += DRAW_TOP * FILE_WIDTH / 4 +

for(i=0; i

{

memcpy(lpSurf, lpV, h / 2);

lpV += FILE_WIDTH / 2;

lpSurf += / 2;

}

// fill U data

lpU += DRAW_TOP * FILE_WIDTH / 4 +

for(i=0; i

{

memcpy(lpSurf, lpU, h / 2);

lpU += FILE_WIDTH / 2;

lpSurf += / 2;

}

}

lpDDSOffScr->Unlock(NULL);

delete lpYV12;

// Blt到主表面上

= 0;

= 0;

= h;

= ht;

GetClientRect(hWnd,&rctDest);

ClientToScreen(hWnd, (LPPOINT)&);

ClientToScreen(hWnd, (LPPOINT)&);

DRAW_LEFT

DRAW_LEFT

/ 2;

/ 2;

ddRval = lpDDSPrimary->Blt(&rctDest, lpDDSOffScr, &rctSour, DDBLT_WAIT, NULL);

while(ddRval == DDERR_WASSTILLDRAWING);

if(ddRval != DD_OK)

return FALSE;

// 释放DirectDraw对象

if(lpDD != NULL)

{

if(lpDDSPrimary != NULL)

{

lpDDSPrimary->Release();

lpDDSPrimary = NULL;

}

if(lpDDSOffScr != NULL)

{

lpDDSOffScr->Release();

lpDDSOffScr = NULL;

}

lpDD->Release();

lpDD = NULL;

}

return TRUE;

}