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

简介:

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

一、QT:QPainter绘制到QImage

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

QT绘制代码:

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文件即可,如下:

#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个圆形和一个字符串和椭圆,代码如下:

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

 绘制效果如下:

三、性能:待测试 

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/202563.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL根据binlog恢复数据

简介 本文介绍了使用mysqlbinlog导出数据&#xff0c;根据binlog恢复数据&#xff0c;和导出数据时报需要super权限的解决方法。 环境 MySQL: 5.7.40 说明 MySQL的binlog是数据库服务器在运行过程中产生的日志文件&#xff0c;记录了数据库增删改的操作&#xff0c;可用于恢复和…

leetcode二叉树

下面的两个题呢是比较类似的所以放在一起讲&#xff0c;更好的理解起来。 https://leetcode.cn/problems/same-tree/description/ 这个题就是比较两颗树是不是一样的&#xff0c;这个其实看起来就只要比较当前节点&#xff0c;我们分析成子问题就是判断两颗树当前节点是不是一致…

Java实现动态加载的逻辑

日常工作中我们经常遇到这样的场景&#xff0c;某某些逻辑特别不稳定&#xff0c;随时根据线上实际情况做调整&#xff0c;比如商品里的评分逻辑&#xff0c;比如规则引擎里的规则。 常见的可选方案有: JDK自带的ScriptEngine 使用groovy&#xff0c;如GroovyClassLoader、Gro…

《尚品甄选》:后台系统——分类品牌和规格管理(debug一遍)

文章目录 一、分类品牌管理1.1 表结构介绍1.2 列表查询1.3 添加功能1.4 修改功能1.5 删除功能 二、商品规格管理2.1 表结构介绍2.2 列表查询2.3 添加功能2.4 修改功能2.5 删除功能 一、分类品牌管理 分类品牌管理就是将分类的数据和品牌的数据进行关联&#xff0c;分类数据和品…

48、Flink DataStream API 编程指南(1)- DataStream 入门示例

Flink 系列文章 1、Flink 部署、概念介绍、source、transformation、sink使用示例、四大基石介绍和示例等系列综合文章链接 13、Flink 的table api与sql的基本概念、通用api介绍及入门示例 14、Flink 的table api与sql之数据类型: 内置数据类型以及它们的属性 15、Flink 的ta…

Web安全漏洞分析-XSS(中)

随着互联网的迅猛发展&#xff0c;Web应用的普及程度也愈发广泛。然而&#xff0c;随之而来的是各种安全威胁的不断涌现&#xff0c;其中最为常见而危险的之一就是跨站脚本攻击&#xff08;Cross-Site Scripting&#xff0c;简称XSS&#xff09;。XSS攻击一直以来都是Web安全领…

微信小程序本地和真机调试文件上传成功但体验版不成功

可能是微信小程序ip白名单的问题&#xff0c;去微信公众平台&#xff08;小程序&#xff09;上设置小程序的ip白名单 1、在本地中取消不校验 然后在本地去上传文件&#xff0c;就会发现控制台报错了&#xff0c;会提示一个https什么不在ip白名单&#xff0c;复制那个网址 2、…

【中间件】DAL中间件intro

中间件middleware 内容管理 intro数据访问层why use DAL中间件主流DAL中间件方案DAL浅析 本文从理论上介绍一下服务化背景下的DAL中间件的理论并浅析相关中间件 cfeng之前work的时候产品发展到分离服务不分库的阶段&#xff0c;所以根本不需要DAL中间件&#xff0c;也没有分布式…

机器学习——决策树

1.决策树 2.熵&#xff08;不确定程度&#xff09; 3.信息增益 & 信息增益比 3.1 信息增益 & 信息增益比 的 概念 3.2 案例解释说明 &#xff13;.&#xff12;.&#xff11;数据集说明 &#xff13;.&#xff12;.&#xff12;计算 &#xff14;&#xff0e;&#x…

软件设计师——计算机组成原理(一)

&#x1f4d1;前言 本文主要是【计算机组成原理】——软件设计师计算机组成原理的习题&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &…

[React] 2023年最新面试题

[React] 2023年最新面试题 1. class 组件与函数组件的区别2. react 18 新特性有那些?新增 createRoot API自动批处理过渡更新新的Hook 3. redux 和 react-redux 的区别4. redux 中间件的原理5. setState 发生了什么 &#xff0c;render 函数做了什么6. 虚拟DOM&#xff0c; Fi…

海外储能认证标准

北美认证 UL9540 代表一个封装完整的储能系统功能安全认证&#xff0c;关注机械测试&#xff0c;电器测试和环境测试 UL9540A 关注消防本身&#xff0c;UL9540A测试主要从电池储能系统安装参数&#xff0c;安装通风要求&#xff0c;消防设施&#xff0c;消防策略和应对措施…

SpringCloud 一

认识微服务 随着互联网行业的发展&#xff0c;对服务的要求也越来越高&#xff0c;服务架构也从单体架构逐渐演变为现在流行的微服务架构。这些架构之间有怎样的差别呢&#xff1f; 单体架构 单体架构&#xff1a;将业务的所有功能集中在一个项目中开发&#xff0c;打成一个…

springmvc实验(三)——请求映射

【知识要点】 方法映射概念 所谓的方法映射就是将前端发送的请求地址和后端提供的服务方法进行关联。在springMVC框架中主要使用Controller和RequestMapping两个注解符&#xff0c;实现请求和方法精准匹配。注解符Controller Spring中包含了一个Controller接口&#xff0c;但是…

【springboot】Spring 官方抛弃了 Java 8!新idea如何创建java8项目

解决idea至少创建jdk17项目 问题idea现在只能创建最少jdk17&#xff0c;不能创建java8了吗?解决 问题 idea现在只能创建最少jdk17&#xff0c;不能创建java8了吗? 我本来以为是 IDEA 版本更新导致的 Bug&#xff0c;开始还没在意。 直到我今天自己初始化项目时才发现&…

在日常工作中怎么处理vue项目中的错误的?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue项目中的错误如何处理 目录 一、错误类型 二、如何处理 后端接口错误 代码逻辑问题 全局设…

亚马逊云与生成式 AI 的融合:未来展望与综述

文章目录 前言生成式AI的定义生成式 AI应用领域AI办公软件AI创意工具AI企业服务AI网络安全AIIT 运维AI软件开发AI数据智能AI数字代理AI金融AI医疗AI教育AI工业AI汽车AI机器人 后记 前言 在当今数据时代&#xff0c;人工智能和云计算已经成为了企业发展和创新的必不可少的工具。…

YOLOv8独家原创改进:自研独家创新FT_Conv,卷积高效结合分数阶变换

💡💡💡本文自研创新改进:卷积如何有效地和频域结合,引入分数阶傅里叶变换(FrFT)和分数阶Gabor变换(FrGT),最终创新到YOLOv8。 使用方法:1)直接替换原来的C2f;2)放在backbone SPPF后使用;等 推荐指数:五星 在道路缺陷检测任务中,原始map为0.8,FT_Conv为0.82 收…

顺丰JAVA开发一面—面试实战经验分析【已通过】

文章目录 面试总结面试开始项目相关基础知识反问环节 顺丰JAVA开发一面面试过程中的问题确实涵盖了很多方面&#xff0c;从项目架构到基础知识再到具体技术细节都有所涉及。 面试官的提问风格也是比较开放的&#xff0c;注重考察面试者的深度理解和解决问题的能力。以下是对每个…

vulnhub-dc1靶场

DC1 配置环境vmware17 nat网络配置 下载地址:DC and Five86 Series Challenges - DC-1 攻击机kali与其在同一网段下 ip:192.168.31.131 信息收集 arp-scan -l #内网探测&#xff0c;扫描目标ip发现目标ip192.168.31.135 使用nmap对目标进行扫描 nmap -T4 -sV -O -A -P …