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; }
发布评论