极速导航
- 创建新项目:002-DrawJunpei
- WIC 是什么
- 用 WIC 加载图片
- 画淳平
创建新项目:002-DrawJunpei
- 右键解决方案 -> 添加 -> 新建项目
- 选择"空项目",项目名称为 “002-DrawJunpei”,然后按"创建"
- 将 “佐佐木淳平.jpg” 移动到项目文件夹里
WIC 是什么
WIC (32位 Windows 映像组件) 其实就是一个图像处理框架,在 Windows Vista 的时候,微软把 GDI+ 里面的 Image 类关于图片解编码的部分单独拆出来,弄成了一套组件,这样所有的 DirectX 套件都能共用这个图像处理组件了。
用 WIC 加载图片
只需要注意 Direct2D 的渲染目标是自带 WIC 位图转 D2D 位图的方法的 (CreateBitmapFromWicBitmap),Direct2D 要求位图格式都是 GUID_WICPixelFormat32bppPBGRA 这点即可。
// 创建 WIC 工厂
CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_WICFactory));
// 读取图片数据并创建解码器
m_WICFactory->CreateDecoderFromFilename(L"佐佐木淳平.jpg", nullptr, GENERIC_READ,
WICDecodeMetadataCacheOnDemand, &m_BitmapDecoder);
// 读取一帧图片
m_BitmapDecoder->GetFrame(0, &m_DecodeFrame);
// 创建转换器
m_WICFactory->CreateFormatConverter(&m_Converter);
// 将图片进行转换,注意 D2D 位图格式都是 GUID_WICPixelFormat32bppPBGRA
m_Converter->Initialize(m_DecodeFrame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0, WICBitmapPaletteTypeCustom);
// 将 WIC 位图转换成 D2D 位图
m_RenderTarget->CreateBitmapFromWicBitmap(m_Converter.Get(), &m_Bitmap);
画淳平
#include<Windows.h>
#include<wincodec.h>
#include<wrl.h>
#include<d2d1.h>
#pragma comment(lib, "d2d1.lib")
#pragma comment(lib, "windowscodecs.lib")
using namespace Microsoft::WRL;
LRESULT CALLBACK callBackFunc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
ComPtr<ID2D1Factory> m_D2DFactory; // D2D 工厂
ComPtr<ID2D1HwndRenderTarget> m_RenderTarget; // 窗口渲染目标
ComPtr<ID2D1SolidColorBrush> m_Brush; // 纯色画刷
ComPtr<ID2D1Bitmap> m_Bitmap; // D2D 位图
ComPtr<IWICImagingFactory> m_WICFactory; // WIC 工厂
ComPtr<IWICBitmapDecoder> m_BitmapDecoder; // 位图解码器
ComPtr<IWICBitmapFrameDecode> m_DecodeFrame; // 位图解码帧
ComPtr<IWICFormatConverter> m_Converter; // 位图转换器
int WINAPI WinMain(HINSTANCE hins, HINSTANCE hPrev, LPSTR lpstr, int cmdShow)
{
WNDCLASS wc = {};
wc.hInstance = hins;
wc.lpszClassName = L"D2D";
wc.lpfnWndProc = callBackFunc;
RegisterClass(&wc);
HWND hwnd = CreateWindow(wc.lpszClassName, L"有", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 768, 512, NULL, NULL, hins, NULL);
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
LRESULT CALLBACK callBackFunc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE: { // 在这里创建 D2D 设备
CoInitialize(nullptr);
// 创建 D2D 工厂
D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, m_D2DFactory.GetAddressOf());
D2D1_RENDER_TARGET_PROPERTIES properties = {};
properties.dpiX = 0;
properties.dpiY = 0;
properties.type = D2D1_RENDER_TARGET_TYPE_HARDWARE; // 硬件渲染
properties.pixelFormat.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED; // 开启 alpha 混合
properties.pixelFormat.format = DXGI_FORMAT_R8G8B8A8_UNORM;
D2D1_HWND_RENDER_TARGET_PROPERTIES Hwndproperties = {};
Hwndproperties.hwnd = hwnd; // 窗口句柄
Hwndproperties.pixelSize.width = 640; // 渲染目标宽度
Hwndproperties.pixelSize.height = 480; // 渲染目标高度
Hwndproperties.presentOptions = D2D1_PRESENT_OPTIONS_NONE; // 自动选择呈现模式
// 创建窗口渲染目标
m_D2DFactory->CreateHwndRenderTarget(properties, Hwndproperties, &m_RenderTarget);
// 创建纯色画刷
m_RenderTarget->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::Blue), &m_Brush);
// 创建 WIC 工厂
CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_WICFactory));
// 读取图片数据并创建解码器
m_WICFactory->CreateDecoderFromFilename(L"佐佐木淳平.jpg", nullptr, GENERIC_READ,
WICDecodeMetadataCacheOnDemand, &m_BitmapDecoder);
// 读取一帧图片
m_BitmapDecoder->GetFrame(0, &m_DecodeFrame);
// 创建转换器
m_WICFactory->CreateFormatConverter(&m_Converter);
// 将图片进行转换,注意 D2D 位图格式都是 GUID_WICPixelFormat32bppPBGRA
m_Converter->Initialize(m_DecodeFrame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0, WICBitmapPaletteTypeCustom);
// 将 WIC 位图转换成 D2D 位图
m_RenderTarget->CreateBitmapFromWicBitmap(m_Converter.Get(), &m_Bitmap);
} break;
case WM_PAINT: { // 在这里进行绘制操作
m_RenderTarget->BeginDraw();
m_RenderTarget->Clear(D2D1::ColorF(D2D1::ColorF::LightSteelBlue)); // 清空窗口
D2D1_RECT_F rect = D2D1::RectF(0, 0, 768, 512);
m_RenderTarget->DrawBitmap(m_Bitmap.Get(), rect);
m_RenderTarget->EndDraw();
} break;
case WM_DESTROY: {
PostQuitMessage(0);
} break;
default: return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
下一章,我们将画淳平的 GIF 动图。