D3D9实现图片显示
#include <directxsdk/d3d9.h>
#include <directxsdk/d3dx9.h>
#include <directxsdk/d3dx9tex.h>
#include "libyuv.h"
#include <windows.h>
#include <iostream>
int width = 1084;
int height = 628;
// 定义YUV图像的宽度和高度
#define WIDTH 1084
#define HEIGHT 628
unsigned char* yuv_data = nullptr;
unsigned char* rgb_data = nullptr;
void yuv420_to_rgb_9(unsigned char* yuv_data, unsigned char* rgb_data, int width, int height)
{
int ySize = width * height;
int uvSize = ySize / 4;
int totalSize = ySize + 2 * uvSize;
// 使用 libyuv 的 YUY2ToI420 函数进行转换
int result = libyuv::I420ToRGB24(
yuv_data, width,
yuv_data + ySize, width / 2,
yuv_data + ySize + uvSize, width / 2,
rgb_data, width * 3,
width, height);
}
int read_yuv() {
FILE* file = NULL;
int err = fopen_s(&file, "input.yuv", "rb");
if (err) {
perror("Failed to open file");
return -1;
}
yuv_data = (unsigned char*)malloc(WIDTH * HEIGHT * 3 / 2);
rgb_data = (unsigned char*)malloc(WIDTH * HEIGHT * 4);
fread(yuv_data, 1, WIDTH * HEIGHT * 3 / 2, file);
//fread(rgb_data, 1, WIDTH * HEIGHT * 3 / 2, file);
fclose(file);
yuv420_to_rgb_9(yuv_data, rgb_data, WIDTH, HEIGHT);
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
read_yuv();
// 注册窗口类
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = "D3DWindowClass";
RegisterClass(&wc);
// 创建窗口
HWND hwnd = CreateWindowEx(
0,
"D3DWindowClass",
"D3D Window",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, width, height,
NULL, NULL, hInstance, NULL
);
if (!hwnd) {
std::cerr << "Failed to create window." << std::endl;
return -1;
}
ShowWindow(hwnd, nCmdShow);
// 初始化Direct3D
IDirect3D9* d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!d3d) {
std::cerr << "Failed to create D3D object." << std::endl;
return -1;
}
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
IDirect3DDevice9* device;
if (FAILED(d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &device))) {
std::cerr << "Failed to create D3D device." << std::endl;
d3d->Release();
return -1;
}
// 加载图片
IDirect3DSurface9* surface;
if (FAILED(device->CreateOffscreenPlainSurface(width, height
, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &surface, NULL))) {
std::cerr << "Failed to create surface." << std::endl;
device->Release();
d3d->Release();
return -1;
}
// 从文件加载图像到表面
//HRESULT hr = D3DXLoadSurfaceFromFile(
// surface, // 目标表面
// NULL, // 目标调色板
// NULL, // 目标矩形
// "D:\\image.png", // 源文件路径
// NULL, // 源矩形
// D3DX_FILTER_NONE, // 过滤器
// 0xFF000000, // 颜色键
// NULL // 图像信息
//);
D3DLOCKED_RECT lockedRect;
if (FAILED(surface->LockRect(&lockedRect, NULL, D3DLOCK_DISCARD))) {
std::cerr << "Failed to lock surface!" << std::endl;
return S_FALSE;
}
// 计算每个像素的字节数(假设每个像素是 24 位 RGB)
int bytesPerPixel = 3;
// 遍历每个像素并将其数据复制到表面
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
BYTE* destPixel = (BYTE*)lockedRect.pBits + y * lockedRect.Pitch + x * 4;
const BYTE* srcPixel = rgb_data + y * width * bytesPerPixel + x * bytesPerPixel;
//复制 RGB 数据
destPixel[0] = srcPixel[0]; // R
destPixel[1] = srcPixel[1]; // G
destPixel[2] = srcPixel[2]; // B
destPixel[3] = 0x00; // A
}
}
//memcpy(lockedRect.pBits, rgb_data, width * height * 4 );
// 解锁表面
if (FAILED(surface->UnlockRect())) {
std::cerr << "Failed to unlock surface!" << std::endl;
return S_FALSE;
}
//if (FAILED(hr)) {
// std::cerr << "Failed to load image from file." << std::endl;
// surface->Release();
// device->Release();
// d3d->Release();
// return -1;
//}
// 渲染循环
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
// 清除屏幕
device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
// 开始场景
device->BeginScene();
// 将表面绘制到屏幕上
LPDIRECT3DSURFACE9 backBuffer;
device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);
device->StretchRect(surface, NULL, backBuffer, NULL, D3DTEXF_NONE);
// 结束场景
device->EndScene();
// 交换缓冲区
device->Present(NULL, NULL, NULL, NULL);
}
// 释放资源
surface->Release();
device->Release();
d3d->Release();
return 0;
}
PS:会笑的人,运气通常都会比别人好。
posted on 2024-10-12 16:19 thinkinc999 阅读(7) 评论(0) 编辑 收藏 举报