canvas教程

UWP中的Direct2D(3)

字号+ 作者:H5之家 来源:H5之家 2017-09-20 17:57 我要评论( )

对于 SurfaceImageSource ,除了转换成 ISurfaceImageSourceNative 接口外,还能转换成 ISurfaceImageSourceNativeWithD2D 接口,区别就在于withD2D的这一个,可以在后台线程上画图,只要在UI线程上刷新就可以了。

对于SurfaceImageSource,除了转换成ISurfaceImageSourceNative接口外,还能转换成ISurfaceImageSourceNativeWithD2D接口,区别就在于withD2D的这一个,可以在后台线程上画图,只要在UI线程上刷新就可以了。

SurfaceImageSource还有一个子类,VirtualSurfaceImageSource,它主要是起虚拟化的作用,用于图像区域比可视区域大的情况,比如地图。

附录

[1] 关于Direct2D:

https://msdn.microsoft.com/zh-cn/library/windows/desktop/dd370987(v=vs.85).aspx

[2] DirectX 和 XAML 互操作

https://msdn.microsoft.com/zh-cn/library/windows/apps/hh825871.aspx

[3] SurfaceImageSource类:

https://msdn.microsoft.com/zh-cn/library/windows/apps/windows.ui.xaml.media.imaging.surfaceimagesource.aspx

[4] ISurfaceImageSourceNative接口:

 https://msdn.microsoft.com/zh-cn/library/windows/apps/hh848322.aspx

 

完整代码

MainPage.xaml.h

// // MainPage.xaml.h // Declaration of the MainPage class. // #pragma once #include App2 { An empty page that can be used on its own or navigated to within a Frame. MainPage sealed { public: MainPage(); void OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) override; private: void OnButtonClick(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e); void CreateDevice(); Microsoft::WRL::ComPtr<IWICBitmapSource> LoadImageByWIC(const wchar_t* file); Microsoft::WRL::ComPtr<IWICBitmapSource> GetMask(IWICBitmapSource* src); void Draw(ISurfaceImageSourceNative* sisn, const wchar_t* mask); HRESULT PrepareDraw(ISurfaceImageSourceNative* sisn, const RECT& updateRect, IDXGISurface** surface, POINT* offset); Microsoft::WRL::ComPtr<IWICImagingFactory> m_factory; Microsoft::WRL::ComPtr<IDXGIDevice> m_dxgiDevice; Microsoft::WRL::ComPtr<ID2D1DeviceContext> m_d2dDeviceContext; Microsoft::WRL::ComPtr<IWICBitmapSource> m_img; }; }

View Code

MainPage.xaml.cpp

// // MainPage.xaml.cpp // Implementation of the MainPage class. // #include #include App2; using namespace Platform; using namespace Windows::Foundation; using namespace Windows::Foundation::Collections; using namespace Windows::UI::Xaml; using namespace Windows::UI::Xaml::Controls; using namespace Windows::UI::Xaml::Controls::Primitives; using namespace Windows::UI::Xaml::Data; using namespace Windows::UI::Xaml::Input; using namespace Windows::UI::Xaml::Media; using namespace Windows::UI::Xaml::Media::Imaging; using namespace Windows::UI::Xaml::Navigation; using namespace Microsoft::WRL; using namespace std; #define HR(exp) hr = exp; assert(SUCCEEDED(hr)) MainPage::MainPage() { InitializeComponent(); } void MainPage::OnNavigatedTo(Windows::UI::Xaml::Navigation::NavigationEventArgs^ e) { for (UIElement^ uiElem : btns->Children) { auto btn = safe_cast<Button^>(uiElem); btn->Click += ref new RoutedEventHandler(this, &MainPage::OnButtonClick); } CreateDevice(); HRESULT hr; HR(CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&m_factory))); m_img = LoadImageByWIC(L); } void MainPage::CreateDevice() { static D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_9_2, D3D_FEATURE_LEVEL_9_1 }; HRESULT hr; ComPtr<ID3D11Device> d3dDevice; ComPtr<ID2D1Device> d2dDevice; HR(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, D3D11_CREATE_DEVICE_BGRA_SUPPORT, featureLevels, extent<decltype(featureLevels)>::value, D3D11_SDK_VERSION, &d3dDevice, nullptr, nullptr)); HR(d3dDevice.As(&m_dxgiDevice)); HR(D2D1CreateDevice(m_dxgiDevice.Get(), nullptr, &d2dDevice)); HR(d2dDevice->CreateDeviceContext(D2D1_DEVICE_CONTEXT_OPTIONS_NONE, &m_d2dDeviceContext)); } ComPtr<IWICBitmapSource> MainPage::LoadImageByWIC(const wchar_t* file) { ComPtr<IWICBitmapDecoder> decoder; ComPtr<IWICBitmapFrameDecode> frame; ComPtr<IWICFormatConverter> converter; HRESULT hr; HR(m_factory->CreateDecoderFromFilename(file, nullptr, GENERIC_READ, WICDecodeMetadataCacheOnDemand, &decoder)); HR(decoder->GetFrame(0, &frame)); HR(m_factory->CreateFormatConverter(&converter)); HR(converter->Initialize( frame.Get(), GUID_WICPixelFormat32bppPBGRA, // Pre-multipled BGRA WICBitmapDitherTypeNone, nullptr, 0, WICBitmapPaletteTypeCustom)); return converter; } ComPtr<IWICBitmapSource> MainPage::GetMask(IWICBitmapSource* src) { uint32_t width, height; src->GetSize(&width, &height); size_t len = width * 4 * height; unique_ptr<byte[]> pixels(new byte[len]); src->CopyPixels(nullptr, width * 4, len, pixels.get()); for (size_t i = 0; i < width * height; i++) { // BGRA. The average of RGB channels is used as Alpha channel. pixels[i * 4 + 3] = (pixels[i * 4] + pixels[i * 4 + 1] + pixels[i * 4 + 2]) / 3; } ComPtr<IWICBitmap> bmp; m_factory->CreateBitmapFromMemory(width, height, GUID_WICPixelFormat32bppPBGRA, width * 4, len, pixels.get(), &bmp); return bmp; } void MainPage::OnButtonClick(Object^ sender, RoutedEventArgs^ e) { HRESULT hr; auto btn = safe_cast<Button^>(sender); auto maskPath = btn->Tag->ToString(); SurfaceImageSource^ sis = ref new SurfaceImageSource(400, 400); ComPtr<ISurfaceImageSourceNative> sisn; HR(reinterpret_cast<IInspectable*>(sis)->QueryInterface(IID_PPV_ARGS(&sisn))); HR(sisn->SetDevice(m_dxgiDevice.Get())); // set device as DXGI device. // Note this auto brush = ref new ImageBrush(); brush->ImageSource = sis; canvas->Fill = brush; Draw(sisn.Get(), maskPath->Data()); } void MainPage::Draw(ISurfaceImageSourceNative* sisn, const wchar_t* mask) { HRESULT hr; ComPtr<IDXGISurface> surface; RECT rect = { 0, 0, 400, 400 }; POINT renderTargetOffset; // view port offset in surface. HR(PrepareDraw(sisn, rect, &surface, &renderTargetOffset)); ComPtr<IWICBitmapSource> maskSrc = GetMask(LoadImageByWIC(mask).Get()); ComPtr<ID2D1Bitmap> maskBmp; ComPtr<ID2D1Bitmap> imgBmp; ComPtr<ID2D1BitmapBrush> imgBrush; ComPtr<ID2D1Bitmap1> tgrBmp; // Note ID2D1Bitmap1 HR(m_d2dDeviceContext->CreateBitmapFromWicBitmap(maskSrc.Get(), &maskBmp)); HR(m_d2dDeviceContext->CreateBitmapFromWicBitmap(m_img.Get(), &imgBmp)); HR(m_d2dDeviceContext->CreateBitmapBrush(imgBmp.Get(), &imgBrush)); HR(m_d2dDeviceContext->CreateBitmapFromDxgiSurface(surface.Get(), nullptr, &tgrBmp)); m_d2dDeviceContext->SetTarget(tgrBmp.Get()); m_d2dDeviceContext->BeginDraw(); m_d2dDeviceContext->SetTransform(D2D1::Matrix3x2F::Translation(renderTargetOffset.x, renderTargetOffset.y)); m_d2dDeviceContext->Clear({0, 0, 1, 1}); // Clear with blue color. m_d2dDeviceContext->SetAntialiasMode(D2D1_ANTIALIAS_MODE_ALIASED); // Must set antialias mode. m_d2dDeviceContext->FillOpacityMask(maskBmp.Get(), imgBrush.Get()); HR(m_d2dDeviceContext->EndDraw()); m_d2dDeviceContext->SetTarget(nullptr); HR(sisn->EndDraw()); } HRESULT MainPage::PrepareDraw(ISurfaceImageSourceNative* sisn, const RECT& updateRect, IDXGISurface** surface, POINT* offset) { HRESULT hr; hr = sisn->BeginDraw(updateRect, surface, offset); if ((hr == DXGI_ERROR_DEVICE_REMOVED) || (hr == DXGI_ERROR_DEVICE_RESET)) { CreateDevice(); PrepareDraw(sisn, updateRect, surface, offset); } else { return hr; } }

View Code

MainPage.xaml见正文。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • HTML5+CSS+jQuery综合案例提高教程

    HTML5+CSS+jQuery综合案例提高教程

    2017-09-19 16:11

  • Developing realistic shaders in Arnold for Cinema 4d , Vol.

    Developing realistic shaders in Arnold for Cinema 4d , Vol.

    2017-09-19 11:03

  • Android实现界面实时更新

    Android实现界面实时更新

    2017-09-17 18:19

  • NView模板绘制原生列表教程

    NView模板绘制原生列表教程

    2017-09-15 09:00

网友点评