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;
}

posted on 2024-10-12 16:19  thinkinc999  阅读(7)  评论(0编辑  收藏  举报

导航