004:Direct 2D离屏渲染(Qt中实现)

简介:

用QT开发图像显示的小程序,需要一些标注工具,由于用的是opengl渲染,所以就在内存中进行绘制,然后纹理贴图贴出去,发现Qt绘制的效果太差,且速度一般,于是就想着用direct2d来绘制需要的纹理图像。

一、QT:QPainter绘制到QImage

下图是QT直接在QImage对象上绘制的效果,其中QImage长和宽分别为:564 - 466。在打开反走样的设置下,线段和椭圆中的锯齿非常明显,字体绘制的也非常丑陋。

QT绘制代码:

cpp 复制代码
void YGLayerScreen::UpdateQImage(){
	if (m_QImage.isNull())
		return;

	QFont m_Font;
	m_Font.setPixelSize(36);
	m_Font.setStyleStrategy(QFont::PreferAntialias);

	QPainter painter;
	if (!painter.begin(&m_QImage))
		return;

	painter.setPen(QPen(Qt::red, 1));
	painter.setFont(m_Font);

	painter.setRenderHints(QPainter::TextAntialiasing|QPainter::Antialiasing | QPainter::SmoothPixmapTransform);

	painter.drawEllipse(QPoint(m_TextureCol/2, m_TextureRow/2),100,200);
	painter.drawLine(10, 10, m_TextureCol / 2, 30);
	painter.drawText(QPoint(50, 50), QString::fromLocal8Bit("你好123TEXTtext"));
	painter.end();

}

二、Direct2D绘制

QT中Direct2D的配置(非常简单),添加头文件和对应的Lib文件即可,如下:

cpp 复制代码
#include <wrl.h>
#include <windows.h>
#include <d2d1.h>
#include <dwrite.h>
#include <wincodec.h>
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "Dwrite.lib")
#pragma comment(lib, "windowscodecs.lib")

在窗口中随机绘制100个圆形和一个字符串和椭圆,代码如下:

cpp 复制代码
void QtOpenGL::TestDirect2D()
{
	/* 统计运行时间 */
	LARGE_INTEGER start_counter, end_counter, counters, nFreq;
	QueryPerformanceFrequency(&nFreq);
	QueryPerformanceCounter(&start_counter);

	/* 离屏渲染图像的宽高 */
	UINT uiWidth = 512;// 1920;
	UINT uiHeight = 512;// 1080;

	/* IWIC 相关变量 */
	IWICBitmap *pBitmap = NULL;
	IWICImagingFactory* pImageFactory = NULL;

	/* IDWrite 相关变量 */
	IDWriteTextFormat *pTextFormat = NULL;
	IDWriteFactory* pDWriterFactory = NULL;   /* use the DrawText method */
	static const WCHAR msc_fontName[] = L"Verdana";
	static const FLOAT msc_fontSize = 50;


	HRESULT hr = CoCreateInstance(
		CLSID_WICImagingFactory,
		NULL,
		CLSCTX_INPROC_SERVER,
		IID_IWICImagingFactory,
		(LPVOID*)&pImageFactory
	);
	if (SUCCEEDED(hr)) {
		//WICPixelFormatGUID formatGUID = GUID_WICPixelFormat32bppBGRA;
		hr = pImageFactory->CreateBitmap(uiWidth, uiHeight,
			GUID_WICPixelFormat32bppPBGRA,
			WICBitmapCacheOnLoad, &pBitmap);
		if (SUCCEEDED(hr)) {
			int a = 0;
		}
	}

	/* */
	hr = DWriteCreateFactory( DWRITE_FACTORY_TYPE_SHARED,
		__uuidof(pDWriterFactory),
		reinterpret_cast<IUnknown **>(&pDWriterFactory)
	);

	// Create a DirectWrite text format object.
	hr = pDWriterFactory->CreateTextFormat(msc_fontName, NULL,
		DWRITE_FONT_WEIGHT_NORMAL,
		DWRITE_FONT_STYLE_NORMAL,
		DWRITE_FONT_STRETCH_NORMAL,
		msc_fontSize,
		L"", //locale
		&pTextFormat
	);

	pTextFormat->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
	pTextFormat->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);



	ID2D1Factory *m_pD2DFactory = NULL;

		//ID2D1DCRenderTarget *m_pRenderTarget = NULL;
	hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &m_pD2DFactory);

	if (SUCCEEDED(hr))
	{


		// Create a DC render target.
		D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
			D2D1_RENDER_TARGET_TYPE_DEFAULT,
			D2D1::PixelFormat(
				DXGI_FORMAT_B8G8R8A8_UNORM,
				D2D1_ALPHA_MODE_PREMULTIPLIED),
			0,
			0,
			D2D1_RENDER_TARGET_USAGE_NONE,
			D2D1_FEATURE_LEVEL_DEFAULT
		);

		ID2D1RenderTarget* m_Target = NULL;
		hr = m_pD2DFactory->CreateWicBitmapRenderTarget(pBitmap, &props, &m_Target);

		D2D1_SIZE_F rtSize = m_Target->GetSize();
		// Draw a grid background.
		int width = static_cast<int>(rtSize.width);
		int height = static_cast<int>(rtSize.height);

		ID2D1SolidColorBrush* pBlackBrush = NULL;
		hr = m_Target->CreateSolidColorBrush(
			D2D1::ColorF(D2D1::ColorF::Red),//颜色
			&pBlackBrush//接收画刷
		);


		static const WCHAR sc_txt[] = L"你好!Direct 2D!";

		if (SUCCEEDED(hr))
		{
			m_Target->BeginDraw();
			m_Target->Clear(D2D1::ColorF(0.26f, 0.56f, 0.87f));
			m_Target->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(150, 55), 50, 30), pBlackBrush);
			m_Target->DrawTextW(
				sc_txt, 
				ARRAYSIZE(sc_txt) - 1,
				pTextFormat,
				D2D1::RectF(0, 0, uiWidth/2, uiHeight/2),
				pBlackBrush);

			for (int i = 0; i < 100; ++i)
			{
				FLOAT left = rand() % width;
				FLOAT top = rand() % height;
				FLOAT radius = rand() % 200;
				pBlackBrush->SetColor(D2D1::ColorF(rand() % 100 / 100.f, rand() % 100 / 100.f, rand() % 100 / 100.f, 100));
				//CD2DEllipse ellipse(CD2DRectF(left, top, left + radius, top + radius));
				//CD2DSolidColorBrush brush(pRenderTarget, D2D1::ColorF(rand() % 100 / 100.f, rand() % 100 / 100.f, rand() % 100 / 100.f, 100));
				m_Target->DrawEllipse(D2D1::Ellipse(D2D1::Point2F(left, top), radius, radius), pBlackBrush);
				//pRenderTarget->FillEllipse(ellipse, &brush);
			}

			m_Target->EndDraw();
		}


		IWICBitmapLock *pLock = NULL;
		WICRect rcLock = { 0, 0, uiWidth, uiHeight };
		hr = pBitmap->Lock(&rcLock, WICBitmapLockWrite, &pLock);
		if (SUCCEEDED(hr))
		{
			UINT cbBufferSize = 0;
			UINT cbStride = 0;
			BYTE *pv = NULL;

			hr = pLock->GetStride(&cbStride);

			if (SUCCEEDED(hr))
			{
				hr = pLock->GetDataPointer(&cbBufferSize, &pv);
				FILE* pFile = fopen("bmp512.raw", "wb+");
				fwrite(pv, 1, cbBufferSize, pFile);
				fclose(pFile);
			}

			// Clear the image data
			//ZeroMemory(pv, cbBufferSize);

			// Release the bitmap lock.
			pLock->Release();
		}
	}

	if (pBitmap) {
		pBitmap->Release();
	}

	if (pImageFactory) {
		pImageFactory->Release();
	}

	QueryPerformanceCounter(&end_counter);
	counters.QuadPart = end_counter.QuadPart - start_counter.QuadPart;

	LONGLONG fps = nFreq.QuadPart / counters.QuadPart;
	LONGLONG elapsed = counters.QuadPart * 1000 / nFreq.QuadPart;

	qDebug() << "FPS :" << fps << "ms";
	qDebug() << "TIMES :" << elapsed << "ms";
	start_counter = end_counter;
}

绘制效果如下:

三、性能:待测试

由于绘制的内容不同,暂时没对性能进行测试。

相关推荐
shinelord明8 分钟前
【再谈设计模式】享元模式~对象共享的优化妙手
开发语言·数据结构·算法·设计模式·软件工程
Monly2114 分钟前
Java(若依):修改Tomcat的版本
java·开发语言·tomcat
boligongzhu15 分钟前
DALSA工业相机SDK二次开发(图像采集及保存)C#版
开发语言·c#·dalsa
Eric.Lee202116 分钟前
moviepy将图片序列制作成视频并加载字幕 - python 实现
开发语言·python·音视频·moviepy·字幕视频合成·图像制作为视频
7yewh18 分钟前
嵌入式Linux QT+OpenCV基于人脸识别的考勤系统 项目
linux·开发语言·arm开发·驱动开发·qt·opencv·嵌入式linux
waicsdn_haha30 分钟前
Java/JDK下载、安装及环境配置超详细教程【Windows10、macOS和Linux图文详解】
java·运维·服务器·开发语言·windows·后端·jdk
_WndProc32 分钟前
C++ 日志输出
开发语言·c++·算法
qq_4335545440 分钟前
C++ 面向对象编程:+号运算符重载,左移运算符重载
开发语言·c++
数据小爬虫@1 小时前
如何高效利用Python爬虫按关键字搜索苏宁商品
开发语言·爬虫·python
ZJ_.1 小时前
WPSJS:让 WPS 办公与 JavaScript 完美联动
开发语言·前端·javascript·vscode·ecmascript·wps