将24位BGR图像从内存加载到ID2D1Bitmap1

时间:2015-08-05 08:25:35

标签: optimization bitmap directx-11

我在内存中有一个BGR 24位图像作为连续缓冲区(由cv::Mat表示,以防它可能有任何帮助)。我想将其加载到ID2D1Bitmap1位图以进行2D渲染。我有以下工作代码(在这里显示伪代码):

IWICImagingFactory::CreateBitmapFromMemory(GUID_WICPixelFormat24bppBGR);
IWICFormatConverter::Initialize(GUID_WICPixelFormat32bppRGB);
ID2D1DeviceContext::CreateBitmapFromWicBitmap;

这很好用,主要问题是花费的时间:20-40毫秒,这对我的应用来说太长了。我正在寻找优化流程的方法。

我可能可以通过这样做一次保存ID2D1Bitmap1的创建时间,然后使用CopyFromMemory从内存加载转换后的图像,但转换本身仍需要大量时间。一种方法是将原始BGR缓冲区加载到GPU内存,并将其转换为GPU本身的 native RGBA格式,但我不知道如何开始。

1 个答案:

答案 0 :(得分:0)

你的第二个想法正是你应该去的方向。创建ID2D1Bitmap(s)一次,转换缓冲区(更多内容如下),并使用CopyFromMemory。我在一个应用程序中做了类似的事情,它提供了连接网络摄像头的预览(可能有各种格式之一)。有些相机会以MJPEG,YUY2等形式传送图像。

该应用使用MediaFoundationIMFTransform来转换缓冲区。在这种情况下,IMFTransformCLSID_CColorConvertDMO的实例(在可能的情况下使用SIMD寄存器/指令)。但是,在完成之前,我使用自己的转换代码进行了测试(这是受CPU限制的,并且执行得如此),另一个使用HLSLDirectCompute的解决方案(表现良好,但只处理了一个)格式)。最后,我选择CLSID_CColorConvertDMO来处理各种类型的输入,但是如果你只有一种已知的类型,你可以选择使用HLSL解决方案(尽管它会导致你必须编写转换代码,并设置数据的“视图”。

但是,如果您选择MediaFoundation路线,则可以使用IMFTransform而不使用图表的其余部分(来源,接收器等)。创建CLSID_CColorConvertDMO实例并设置输入和输出类型(格式,帧大小等)后,创建IMFSample(使用MFCreateSample)和IMFMediaBuffer(使用MFCreateMemoryBuffer)对样本(使用IMFSample::AddBuffer),然后所有必要的是调用ProcessInputProcessOutput来转换缓冲区(预先创建所有项目)。这可能听起来很多,但如果操作正确,您的CPU利用率将不会产生明显影响,您将获得所需的性能,即使对于通常以60 + FPS提供大帧的捕获卡(使用DataPath)和过去的Blackmagic采集卡。)

祝你好运。我相信你会粉碎它。