栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

Direct2D的C++自制辅助库———D2DEngine (持续更新)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Direct2D的C++自制辅助库———D2DEngine (持续更新)

目录
  • 前言
  • D2DEngine库
    • D2D_PICTURE.H
    • D2D_PICTURE.CPP
    • D2D_DRAW.H
    • D2D_DRAW.CPP
  • 后记

前言 D2DEngine库

参考了以下大神的链接:
D3D12部分教程:GameBabyRockSun_QQ
D2D入门教程:MoonlightDesigner

此库开始于2022.7.20,一开始我发现网上很多D2D教程很繁琐,原因有像ID2D1Bitmap* Bitmap这样直接调用指针的,用完还要记得释放赋值NULL,也有在WinMain函数和回调函数调用各种函数的,导致写的代码很混乱,创建设备和渲染分不清楚。

我从去年开始想做一个封装D2D的库,先是照着主流教程做了一遍,发现各种内存错误,网上也找不到解决方法。于是项目停了一会。之后稍微学了一下D3D的部分教程,发现管理各种D2D & WIC 设备可以借助微软的COM接口省一半力。

下面的库就是将有关D2D和WIC的设备集成到一个叫 D2DEngine 的接口上,单独分出一个储存图像信息的 Picture 的接口,这样就能非常方便使用Direct2D绘制图像了。

代码可以全部复制使用,放到一个项目上,推荐在Visual Studio系列食用,效果更佳,如图:

另外,第一次编译出现错误:“非常量引用的初始值必须为左值” 的解决方法
可以参考我的D2DEngine第一篇教程:https://blog.csdn.net/DGAF2198588973/article/details/125911630

D2D_PICTURE.H
#pragma once

#ifndef D2D_PICTURE_H_
#define D2D_PICTURE_H_

#include
using namespace Microsoft;
using namespace Microsoft::WRL;
#include


typedef enum Picture_Type
{
	SINGLE_FRAME,  //单帧图片
	MULTI_FRAME    //多帧图片,如GIF
} Picture_Type;




//图片类,必须提供图片信息
//可以使用vector类存储一组图片
class Picture : public ComPtr
{
public:
	Picture(WCHAR* FileName) : PictureFileName(FileName) {};

	
	Picture() { PictureFileName = nullptr; }


public:

	//获取Picture类内部存储的图片路径
	inline WCHAR* GetPictureFileName() { return PictureFileName; }

	//改变Picture类存储的图片文件路径
	bool ChangeFileName(WCHAR* Filename);

	//检测图片路径是否存在
	bool CheckFileIfExist(WCHAR* Filename);

private:

    //Picture类单独存储的图片路径
	WCHAR* PictureFileName;

};



#endif 
D2D_PICTURE.CPP
#include "D2D_PICTURE.h"
#include 



bool Picture::ChangeFileName(WCHAR* Filename)
{
	if (!(PictureFileName = Filename))
	{
		return false;
	}
	return true;
}



bool Picture::CheckFileIfExist(WCHAR* Filename)
{
	std::fstream f;
	f.open(Filename,std::ios::in);
	if (f.good())
	{
		f.close();
		return true;
	}
	else
	{
		f.close();
		return false;
	}
}



D2D_DRAW.H
#pragma once

#ifndef D2D_DRAW_H_
#define D2D_DRAW_H_

#include
using namespace Microsoft;
using namespace Microsoft::WRL;
#include
using namespace D2D1;
#include
#include
using namespace std;

#include "D2D_PICTURE.h"

#pragma comment(lib,"d2d1.lib")




//用于检测COM,WIC组件的错误
class D2DException
{
public:
	D2DException(HRESULT hr) : m_hrError(hr)
	{
	}
	HRESULT Error() const
	{
		return m_hrError;
	}
private:
	const HRESULT m_hrError;
};






//D2D图形引擎接口
class D2DEngine
{

private:

	ComPtr D2DFactory;
	ComPtr D2DRenderTarget;
	ComPtr D2DBrush;
	


private:

	ComPtr WICFactory;
	ComPtr WICDecoder;
	ComPtr WICFrame;
	ComPtr WICFormatConverter;




public:


	//构造函数
	D2DEngine();


	void BeginDraw();
	void EndDraw();


	//初始化函数,D2DEngine的任何操作都要先经这一步
	//一参句柄必填,二参表示画刷,默认为白色
	bool Initialize(const HWND hwnd, const ColorF::Enum BrushColor = ColorF::White);


	//清屏并填充背景色,默认白色
	void Clear(const ColorF::Enum ClearColor = ColorF::White);


	//绘制单帧图片 (XY坐标,宽,高)
	void DrawPicture(Picture Bitmap, double x, double y, double width, double height);





public: //以下函数使用了WIC库

	
	//对图片格式进行转换,图片只有被转换成D2D位图才能加载操作
	//当转换动图(如GIF)时,需要额外提供一个 vector
	//当转换不支持的图片时,会返回false
	bool TransformPictureIntoBitmap(
		Picture& Bitmap, Picture_Type type,
		vector& BitmapGroup = vector());


	
};







#endif
D2D_DRAW.CPP
#include "D2D_DRAW.h"


D2DEngine::D2DEngine()
{
	if (FAILED(::CoInitialize(nullptr)))
	{
		::PostQuitMessage(0);
		::exit(0);
	}
}



bool D2DEngine::Initialize(
	const HWND hwnd, 
	const ColorF::Enum BrushColor
)
{
	try
	{

		D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, IID_PPV_ARGS(&D2DFactory));

		RECT rc = {};
		GetClientRect(hwnd, &rc);

		D2DFactory->CreateHwndRenderTarget(
			RenderTargetProperties(),
			HwndRenderTargetProperties(hwnd, SizeU(rc.right - rc.left, rc.bottom - rc.top)),
			&D2DRenderTarget);

		D2DRenderTarget->CreateSolidColorBrush(ColorF(BrushColor), &D2DBrush);

	}
	catch (D2DException& Error)
	{
		return false;
	}

	return true;
}




void D2DEngine::BeginDraw()
{
	D2DRenderTarget->BeginDraw();
}




void D2DEngine::EndDraw()
{
	D2DRenderTarget->EndDraw();
}




void D2DEngine::Clear(const ColorF::Enum ClearColor)
{
	D2DRenderTarget->Clear(ColorF(ClearColor));
}



bool D2DEngine::TransformPictureIntoBitmap(
	Picture& Bitmap,Picture_Type type,std::vector& BitmapGroup)
{
	try
	{
		WICFactory.Reset();
		WICDecoder.Reset();
		WICFrame.Reset();
		WICFormatConverter.Reset();
		

		CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&WICFactory));

		//通过Picture内部储存的路径将图片读入内存
		WICFactory->CreateDecoderFromFilename(
			Bitmap.GetPictureFileName(),
			nullptr,
			GENERIC_READ,
			WICDecodeMetadataCacheOnDemand,
			&WICDecoder
		);


		if (type == SINGLE_FRAME)
		{
			WICDecoder->GetFrame(0, &WICFrame);

			WICFactory->CreateFormatConverter(&WICFormatConverter);

			//对图片进行格式转换
			WICFormatConverter->Initialize(
				WICFrame.Get(),
				GUID_WICPixelFormat32bppPBGRA,
				WICBitmapDitherTypeNone,
				nullptr,
				0.0f,
				WICBitmapPaletteTypeCustom
			);

			D2DRenderTarget->CreateBitmapFromWicBitmap(WICFormatConverter.Get(), NULL, Bitmap.GetAddressOf());
		}

		else if (type == MULTI_FRAME)
		{
			UINT _framecount;
			WICDecoder->GetFrameCount(&_framecount);
			Picture _bitphoto;

			for (UINT i = 0; i < _framecount; i++)
			{

				WICDecoder->GetFrame(i, &WICFrame);

				WICFactory->CreateFormatConverter(&WICFormatConverter);

				//对图片进行格式转换
				WICFormatConverter->Initialize(
					WICFrame.Get(),
					GUID_WICPixelFormat32bppPBGRA,
					WICBitmapDitherTypeNone,
					nullptr,
					0.0f,
					WICBitmapPaletteTypeCustom
				);

				D2DRenderTarget->CreateBitmapFromWicBitmap(WICFormatConverter.Get(), NULL, _bitphoto.GetAddressOf());
				BitmapGroup.push_back(_bitphoto);

			}

		}
		
	}
	catch (D2DException& Error)
	{
		return false;
	}

	return true;
}






void D2DEngine::DrawPicture(Picture Bitmap, double x, double y, double width, double height)
{
	D2D1_RECT_F imgr = { x,y,width + x,height + y };
	D2DRenderTarget->DrawBitmap(Bitmap.Get(), imgr);
}

后记

本人写D2DEngine库时,正在过暑假,高一升高二。暑期做完作业没什么事,非常喜欢做图像一类的程序,有点不喜欢竞赛。鄙人见识浅陋,肯定有不足之处,大家有意见和问题的在评论区提出就行了

如果大家喜欢,支持我的项目,点个赞就行了,如果有和我一样喜欢或从事图形学的那更好了。

最后,D2DEngine库会在暑期持续更新,教程我会在系列后面提供。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1021824.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号