Direct2D Bitmap操作
加入位图操作需要引入WIC组件,过程将更复杂:
View Code
#include "stdafx.h" D2D1_COLOR_F const COLOR_BLUE = { 0.26f, 0.56f, 0.87f, 1.0f }; D2D1_COLOR_F const COLOR_WHITE = { 1.0f, 1.0f, 1.0f, 1.0f }; D2D1_COLOR_F const COLOR_BLACK = { 0.0f, 0.0f, 0.0f, 1.0f }; D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f, 1.0f }; D2D1_COLOR_F const COLOR_RED = { 1.0f, 0.0f, 0.0f, 1.0f }; struct ComInitialize { ComInitialize() { HR(CoInitialize(nullptr)); } ~ComInitialize() { CoUninitialize(); } }; template <typename T> void CreateInstance(REFCLSID clsid, ComPtr<T>& ptr) { ASSERT(!ptr); HR(CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, __uuidof(T), reinterpret_cast<void **>(ptr.GetAddressOf()))); } struct SampleWindow : DesktopWindow<SampleWindow> { ComPtr<IWICFormatConverter> m_image; ComPtr<ID2D1Bitmap> m_bitmap; D2D1_RECT_F m_location; void CreateDeviceIndependentResources() { ComPtr<IWICImagingFactory> imageFactory; CreateInstance(CLSID_WICImagingFactory, imageFactory); ComPtr<IWICBitmapDecoder> decoder; HR(imageFactory->CreateDecoderFromFilename(L"C:\\Users\\Flysha\\Desktop\\cnblogs.gif", nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, decoder.GetAddressOf())); ComPtr<IWICBitmapFrameDecode> frame; HR(decoder->GetFrame(0, frame.GetAddressOf())); ASSERT(!m_image); HR(imageFactory->CreateFormatConverter(m_image.GetAddressOf())); m_image->Initialize(frame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0, WICBitmapPaletteTypeCustom); } LRESULT MouseMoveHandler(UINT, WPARAM, LPARAM lparam, BOOL&) { WORD x = LOWORD(lparam); WORD y = HIWORD(lparam); D2D1_POINT_2U size; m_image->GetSize(&size.x, &size.y); m_location = RectF(x, y, x + size.x, y + size.y); Invalidate(); return 0; } void CreateDeviceResources() { HR(m_target->CreateBitmapFromWicBitmap(m_image.Get(), m_bitmap.ReleaseAndGetAddressOf())); } void Draw() { m_target->Clear(COLOR_BLUE); m_target->DrawBitmap(m_bitmap.Get(), m_location, 1.0f, D2D1_BITMAP_INTERPOLATION_MODE_LINEAR); } }; int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) { ComInitialize com; SampleWindow window; window.Run(); }
示例中加入了图片随鼠标移动而移动的功能。
可能通过将WIC图片(IWICFormatConverter)转换为D2D图片画笔(ID2D1BitmapBrush),可以设置更多有意思的效果:
View Code
#include "stdafx.h" D2D1_COLOR_F const COLOR_BLUE = { 0.26f, 0.56f, 0.87f, 1.0f }; D2D1_COLOR_F const COLOR_WHITE = { 1.0f, 1.0f, 1.0f, 1.0f }; D2D1_COLOR_F const COLOR_BLACK = { 0.0f, 0.0f, 0.0f, 1.0f }; D2D1_COLOR_F const COLOR_YELLOW = { 0.99f, 0.85f, 0.0f, 1.0f }; D2D1_COLOR_F const COLOR_RED = { 1.0f, 0.0f, 0.0f, 1.0f }; struct ComInitialize { ComInitialize() { HR(CoInitialize(nullptr)); } ~ComInitialize() { CoUninitialize(); } }; template <typename T> void CreateInstance(REFCLSID clsid, ComPtr<T>& ptr) { ASSERT(!ptr); HR(CoCreateInstance(clsid, nullptr, CLSCTX_INPROC_SERVER, __uuidof(T), reinterpret_cast<void **>(ptr.GetAddressOf()))); } struct SampleWindow : DesktopWindow<SampleWindow> { ComPtr<IWICFormatConverter> m_image; ComPtr<ID2D1BitmapBrush> m_brush; D2D1_RECT_F m_location; void CreateDeviceIndependentResources() { ComPtr<IWICImagingFactory> imageFactory; CreateInstance(CLSID_WICImagingFactory, imageFactory); ComPtr<IWICBitmapDecoder> decoder; HR(imageFactory->CreateDecoderFromFilename(L"C:\\Users\\Flysha\\Desktop\\cnblogs.gif", nullptr, GENERIC_READ, WICDecodeMetadataCacheOnLoad, decoder.GetAddressOf())); ComPtr<IWICBitmapFrameDecode> frame; HR(decoder->GetFrame(0, frame.GetAddressOf())); HR(imageFactory->CreateFormatConverter(m_image.GetAddressOf())); HR(m_image->Initialize(frame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0, WICBitmapPaletteTypeCustom)); } LRESULT MouseMoveHandler(UINT, WPARAM, LPARAM lparam, BOOL&) { WORD x = LOWORD(lparam); WORD y = HIWORD(lparam); D2D1_POINT_2U size; m_image->GetSize(&size.x, &size.y); m_location = RectF(x, y, x + (FLOAT)size.x, y + (FLOAT)size.y); Invalidate(); return 0; } void CreateDeviceResources() { ComPtr<ID2D1Bitmap> bitmap; HR(m_target->CreateBitmapFromWicBitmap(m_image.Get(), bitmap.GetAddressOf())); m_target->CreateBitmapBrush(bitmap.Get(), m_brush.ReleaseAndGetAddressOf()); } void Draw() { m_target->Clear(COLOR_BLUE); auto size = m_target->GetSize(); auto rect = RectF(0.0f, 0.0f, size.width, size.height); m_brush->SetExtendModeX(D2D1_EXTEND_MODE_WRAP); m_brush->SetExtendModeY(D2D1_EXTEND_MODE_MIRROR); m_target->FillRectangle(rect, m_brush.Get()); } }; int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) { ComInitialize com; SampleWindow window; window.Run(); }
除此之外,还可以直接将IWICBitmap保存为图形文件:
View Code
#include "stdafx.h" void SaveAs(ComPtr<IWICImagingFactory>& imageFactory, ComPtr<IWICBitmap> & bitmap, PWSTR filename) { ComPtr<IStream> file; HR(SHCreateStreamOnFileEx(filename, STGM_CREATE | STGM_WRITE | STGM_SHARE_EXCLUSIVE, FILE_ATTRIBUTE_NORMAL, TRUE, nullptr, file.GetAddressOf())); ComPtr<IWICBitmapEncoder> encoder; HR(imageFactory->CreateEncoder(GUID_ContainerFormatPng, nullptr, encoder.GetAddressOf())); HR(encoder->Initialize(file.Get(), WICBitmapEncoderNoCache)); ComPtr<IWICBitmapFrameEncode> frame; ComPtr<IPropertyBag2> props; HR(encoder->CreateNewFrame(frame.GetAddressOf(), props.GetAddressOf())); HR(frame->Initialize(props.Get())); UINT width, height; HR(bitmap->GetSize(&width, &height)); HR(frame->SetSize(width, height)); WICPixelFormatGUID pixelFormat; HR(bitmap->GetPixelFormat(&pixelFormat)); HR(frame->SetPixelFormat(&pixelFormat)); HR(frame->WriteSource(bitmap.Get(), nullptr)); HR(frame->Commit()); HR(encoder->Commit()); } int __stdcall wWinMain(HINSTANCE, HINSTANCE, PWSTR, int) { ComInitialize com; ComPtr<IWICImagingFactory> imageFactory; CreateInstance(CLSID_WICImagingFactory, imageFactory); ComPtr<IWICBitmap> bitmap; HR(imageFactory->CreateBitmap(600, 400, GUID_WICPixelFormat32bppPBGRA, WICBitmapCacheOnLoad, bitmap.GetAddressOf())); ComPtr<ID2D1Factory> factory; HR(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, factory.GetAddressOf())); ComPtr<ID2D1RenderTarget> target; HR(factory->CreateWicBitmapRenderTarget(bitmap.Get(), RenderTargetProperties(), target.GetAddressOf())); ComPtr<ID2D1SolidColorBrush> brush; HR(target->CreateSolidColorBrush(COLOR_BLUE, brush.GetAddressOf())); target->BeginDraw(); target->Clear(); target->DrawEllipse(Ellipse(Point2F(300.0f, 200.0f), 100.0f, 180.0f), brush.Get(), 10.0f); HR(target->EndDraw()); PWSTR filename = L"C:\\users\\flysha\\desktop\\cnblogs.png"; SaveAs(imageFactory, bitmap, filename); ShellExecute(nullptr, nullptr, filename, nullptr, nullptr, SW_SHOWDEFAULT); }