将SlimDX.Direct3D11 Texture2D转换为.Net位图 [英] Convert SlimDX.Direct3D11 Texture2D to .Net Bitmap

查看:326
本文介绍了将SlimDX.Direct3D11 Texture2D转换为.Net位图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

将.Net位图转换为SlimDx Texture2D的过程非常快,如下所示: http://www.rolandk.de/index.php?option=com_content&view=article&id=65:bitmap-from-texture-d3d11&catid=16:blog&Itemid=10

Converting an .Net Bitmap to a SlimDx Texture2D works very fast like this: http://www.rolandk.de/index.php?option=com_content&view=article&id=65:bitmap-from-texture-d3d11&catid=16:blog&Itemid=10

private Texture2D TextureFromBitmap(FastBitmapSingle fastBitmap)
{
    Texture2D result = null;
    DataStream dataStream = new DataStream(fastBitmap.BitmapData.Scan0, fastBitmap.BitmapData.Stride * fastBitmap.BitmapData.Height, true, false);
    DataRectangle dataRectangle = new DataRectangle(fastBitmap.BitmapData.Stride, dataStream);
    try
    {
        Texture2DDescription dt = new Texture2DDescription
        {
            BindFlags = BindFlags.ShaderResource,
            CpuAccessFlags = CpuAccessFlags.None,
            Format = Format.B8G8R8A8_UNorm,
            OptionFlags = ResourceOptionFlags.None,
            MipLevels = 1,
            Usage = ResourceUsage.Immutable,
            Width = fastBitmap.Size.X,
            Height = fastBitmap.Size.Y,
            ArraySize = 1,
            SampleDescription = new SampleDescription(1, 0),
        };
        result = new Texture2D(device, dt, dataRectangle);
    }
    finally
    {
        dataStream.Dispose();
    }
    return result;
}

我要使用正确的格式将纹理转换回.Net位图,但这很慢:

For converting the Texture back to a .Net Bitmap in the correct format I use that, but it is very slow:

private bool BitmapFromTexture(FastBitmapSingle fastBitmap, Texture2D texture)
{
    using (MemoryStream ms = new MemoryStream())
    {
        Texture2D.ToStream(device.ImmediateContext, texture, ImageFileFormat.Bmp, ms);
        ms.Position = 0;
        using (Bitmap temp1 = (Bitmap)Bitmap.FromStream(ms))
        {
            Rectangle bounds = new Rectangle(0, 0, temp1.Width, temp1.Height);
            BitmapData BitmapDataIn = temp1.LockBits(bounds, ImageLockMode.ReadWrite, temp1.PixelFormat);
            using (DataStream dataStreamIn = new DataStream(BitmapDataIn.Scan0, BitmapDataIn.Stride * BitmapDataIn.Height, true, false))
            using (DataStream dataStreamOut = new DataStream(fastBitmap.BitmapData.Scan0, fastBitmap.BitmapData.Stride * fastBitmap.BitmapData.Height, false, true))
            {
                dataStreamIn.CopyTo(dataStreamOut);
            }
            temp1.UnlockBits(BitmapDataIn);
            BitmapDataIn = null;
        }
    }
    return true;
}

有没有更快的方法???我做了很多尝试,例如:

Is there a faster way ??? I tried much, such as this:

但是DataRectangle的数据要比我的DataStream中的数据多8倍:

private bool BitmapFromTexture(FastBitmapSingle fastBitmap, Texture2D texture)
{
    using (Texture2D buff = Helper.CreateTexture2D(device, texture.Description.Width, texture.Description.Height, Format.B8G8R8A8_UNorm, BindFlags.None, ResourceUsage.Staging, CpuAccessFlags.Read | CpuAccessFlags.Write))
    {
        device.ImmediateContext.CopyResource(texture, buff);

        using (Surface surface = buff.AsSurface())
        using (DataStream dataStream = new DataStream(fastBitmap.BitmapData.Scan0, fastBitmap.BitmapData.Stride * fastBitmap.BitmapData.Height, false, true))
        {
            DataRectangle rect = surface.Map(SlimDX.DXGI.MapFlags.Read);

            rect.Data.CopyTo(dataStream);

            surface.Unmap();
        }
    }

    return true;
}

有人可以帮忙吗? 复制回我的数据大约需要整个计算时间的50%. 如果可以解决,我的App将会更快...

Can anybody help please? Copying back my data takes about 50% of the whole computation time. If this could be solved, my App would be much faster...

推荐答案

由于以下原因,我找到了解决方案: http://www.rolandk.de/wp/2013/06/inhalt-der-rendertarget-textur-in-ein-bitmap-kopieren/

I found a solution thanks to: http://www.rolandk.de/wp/2013/06/inhalt-der-rendertarget-textur-in-ein-bitmap-kopieren/

但是这个故事有点复杂,因为纹理间距"与位图跨度"不匹配,所以在这里,我的解决方案比我所提出的解决方案快10倍:

But the story is a bit more complicated, because the Texture Pitch doesn't match the Bitmap Stride, so here my solution, 10 times faster than the one in my question:

private bool BitmapFromTexture(FastBitmapSingle fastBitmap, Texture2D texture, int row, int col)
{
    using (Texture2D stage = Helper.CreateStagingTexture(device, fastBitmap.BitmapWidths[col], fastBitmap.BitmapHeights[row]))
    {
        device.ImmediateContext.CopyResource(texture, stage);
        DataStream dsIn;
        DataBox dataBox = device.ImmediateContext.MapSubresource(stage, 0, 0, MapMode.Read, D3D.MapFlags.None, out dsIn);
        int dx = dataBox.RowPitch - fastBitmap.BitmapData[row][col].Stride;
        try
        {
            using (DataStream dsOut = new DataStream(fastBitmap.BitmapData[row][col].Scan0, fastBitmap.BitmapData[row][col].Stride * fastBitmap.BitmapData[row][col].Height, false, true))
            {
                for (int r = 0; r < fastBitmap.BitmapData[row][col].Height; r++)
                {
                    dsOut.WriteRange<byte>(dsIn.ReadRange<byte>(fastBitmap.BitmapData[row][col].Stride));
                    dsIn.Position += dx;
                }
            }
        }
        finally
        {
            device.ImmediateContext.UnmapSubresource(stage, 0);
        }
        dsIn.Dispose();
    }
    return true;
}

这篇关于将SlimDX.Direct3D11 Texture2D转换为.Net位图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆