向左右向右走 —— 小时了了的技术博客

关注C++开发技术、架构设计、软件项目管理、软件产品管理等

在UWP中加载文件一般先创建 StorageFile 对象,然后调用StorageFile.OpenReadAsync 方法得到一个IRandomAccessStream 接口用来读取数据:

1 StorageFile image_file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/sample.jpg", UriKind.Absolute));
2 IRandomAccessStream stream = await image_file.OpenReadAsync();

从一个 IRandomAccessStream 流开始,加载图像的步骤(C++ /CX实现):

1. 转换 IRandomAccessStream^ 到 ISream 接口:

1 ComPtr<IStream> source_stream;
2 DX::ThrowIfFailed(::CreateStreamOverRandomAccessStream(stream, IID_PPV_ARGS(&source_stream)));

2. 调用 IWICImagingFactory::CreateDecoderFromStream 方法(假设IWICImagingFactory对象以创建)创建 IWICBitmapDecoder 对象用于图像解码,并最终得到 IWICFormatConverter 对象转换为适合D2D/D3D的位图格式:

复制代码
ComPtr<IWICBitmapDecoder> decoder;
DX::ThrowIfFailed(_device_resources->GetWicImagingFactory()->CreateDecoderFromStream(source_stream.Get(), nullptr, WICDecodeMetadataCacheOnDemand, &decoder));

ComPtr<IWICBitmapFrameDecode> frame;
DX::ThrowIfFailed(decoder->GetFrame(0, &frame));

// Convert the image to a pixel format supported by Direct2D. 32bppPBGRA is guaranteed to be supported on all hardware.
ComPtr<IWICFormatConverter> covert;
DX::ThrowIfFailed(_device_resources->GetWicImagingFactory()->CreateFormatConverter(&covert));
DX::ThrowIfFailed(covert->Initialize(frame.Get(), GUID_WICPixelFormat32bppPBGRA, WICBitmapDitherTypeNone, nullptr, 0.0f, WICBitmapPaletteTypeCustom));
复制代码

3. 如果图像用于 D2D ,现在就可以直接用 ID2D1DeviceContext::CreateBitmapFromWicBitmap 方法创建 D2D 位图了:

ComPtr<ID2D1Bitmap1> d2d_bitmap;
DX::ThrowIfFailed(_device_resources->GetD2DDeviceContext()->CreateBitmapFromWicBitmap(covert.Get(), &d2d_bitmap));

4. 如果要用于 D3D 则需要先创建 D3D 纹理:

复制代码
// 创建D3D纹理用于3D渲染
D3D11_TEXTURE2D_DESC tex_desc = { 0 };
tex_desc.ArraySize = 1;
tex_desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
tex_desc.CPUAccessFlags = 0;
tex_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
tex_desc.Height = height;
tex_desc.Width = width;
tex_desc.MipLevels = 1;
tex_desc.MiscFlags = 0;
tex_desc.SampleDesc.Count = 1;
tex_desc.SampleDesc.Quality = 0;
tex_desc.Usage = D3D11_USAGE_DEFAULT;

ComPtr<ID3D11Texture2D> image_texture;
DX::ThrowIfFailed(_device_resources->GetD3DDevice()->CreateTexture2D(&tex_desc, NULL, &image_texture));
复制代码

5. 从 ID3D11Texture2D 对象中获取 IDXGISurface 接口,D2D和D3D只能通过DXGI进行交互:

ComPtr<IDXGISurface> dxgi_surface;
DX::ThrowIfFailed(image_texture.As(&dxgi_surface));

6. 通过 ID2D1Factory::CreateDxgiSurfaceRenderTarget 方法创建 D2D 渲染目标:

复制代码
float dpiX = 1.0f;
float dpiY = 1.0f;
_device_resources->GetD2DFactory()->GetDesktopDpi(&dpiX, &dpiY);

D2D1_RENDER_TARGET_PROPERTIES props = D2D1::RenderTargetProperties(
            D2D1_RENDER_TARGET_TYPE_DEFAULT,
            D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
            dpiX,
            dpiY
            );

ComPtr<ID2D1RenderTarget> render_target;
DX::ThrowIfFailed(_device_resources->GetD2DFactory()->CreateDxgiSurfaceRenderTarget(dxgi_surface.Get(), props, &render_target));
复制代码

7. 通过 ID2D1RenderTarget::CreateBitmapFromWicBitmap 方法创建位图(注意这里不能直接使用第3步创建的位图,是不同的渲染目标,设备相关的位图不能通用):

ComPtr<ID2D1Bitmap> bitmap;
DX::ThrowIfFailed(render_target->CreateBitmapFromWicBitmap(covert.Get(), &bitmap));

8. 绘制位图到渲染目标,实际上也是绘制到 D3D 纹理:

render_target->BeginDraw();
render_target->DrawBitmap(bitmap.Get());
render_target->EndDraw();

 

参考:MSDN 《Direct2D 和 Direct3D 互操作性概述》

 

posted on   小时了了  阅读(1131)  评论(0编辑  收藏  举报
编辑推荐:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· C++代码改造为UTF-8编码问题的总结
· DeepSeek 解答了困扰我五年的技术问题
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· 易语言 —— 开山篇
· 【全网最全教程】使用最强DeepSeekR1+联网的火山引擎,没有生成长度限制,DeepSeek本体
< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8

点击右上角即可分享
微信分享提示