2016-05-08 107 views
1

轉換的淨位圖到SlimDx的Texture2D工作非常快這樣的: http://www.rolandk.de/index.php?option=com_content&view=article&id=65:bitmap-from-texture-d3d11&catid=16:blog&Itemid=10轉換SlimDX.Direct3D11的Texture2D到.NET位圖

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位圖我用的,但它是非常緩慢:

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; 
} 

有一個更快的方法???我試過了,像這樣的:

但DataRectangle正好有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%。 如果這可以解決,我的應用程序會更快...

回答

0

我找到了一個解決方案感謝:http://www.rolandk.de/wp/2013/06/inhalt-der-rendertarget-textur-in-ein-bitmap-kopieren/

但故事是一個比較複雜一點,因爲質地間距不我的解決方案,10倍匹配位圖跨越,所以在這裏比在我快問題:

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; 
} 
0

我使用的轉換器是這樣的:

public static BitmapSource Texture2DToBitmapSource(Texture2D texture2D) 
    { 
     using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream()) 
     { 
      Texture2D.ToStream(App.device.ImmediateContext, texture2D, ImageFileFormat.Png, memoryStream); 
      memoryStream.Seek(0, System.IO.SeekOrigin.Begin); 
      return BitmapFrame.Create(memoryStream, BitmapCreateOptions.IgnoreImageCache, BitmapCacheOption.OnLoad); 
     } 
    } 

但是我在使用dpi爲72,而不是一個問題96就像我在我的程序中使用的BitmapSource。希望它有助於一些。

另外我使用SlimDX。

WPF位圖轉換非常令人頭疼。通過進入不安全的代碼和鎖定位來獲得最大速度可能需要從Pbgra和bgra轉換到rgba等。我通常最終返回到舊的繪圖位圖以在許多程序中轉換爲BitmapSource。這個sniplet是我正在使用的,直到我可以從我的計算着色器得到正確的PixelFormat。

 using (System.IO.MemoryStream memoryStream = new System.IO.MemoryStream()) 
     { 
      Texture2D.ToStream(App.device.ImmediateContext, texture, ImageFileFormat.Png, memoryStream); 
      memoryStream.Seek(0, System.IO.SeekOrigin.Begin); 

      //Create an image from a stream. 
      System.Drawing.Image bitmap = System.Drawing.Bitmap.FromStream(memoryStream); memoryStream.Close(); 
      var hBitmap = ((System.Drawing.Bitmap)bitmap).GetHbitmap(); 
      BitmapSource source = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
       hBitmap, 
       IntPtr.Zero, 
       Int32Rect.Empty, 
       BitmapSizeOptions.FromEmptyOptions() 
       ); 
      if (!(source.Width == pixelWidth)) { } 
      if (!(source.Height == pixelHeight)) { } 
      return source; 
     } 

使用從System.Drawing.Image對象的HBITMAP或System.drawing.Bitmap具有超過lockbits和轉化爲不同的PixelFormats更多的控制。舊的CreateBitmap函數和DIB也使用HBITMAP進行轉換。

速度的另一個瓶頸我會想象在Texture2D.ToStream()例程中。這些ImageFileFormat.Png,ImageFileFormat.Bmp,ImageFileFormat.Jpg等SlimDX沒有在Texture2D中添加一些複製功能,並且DX11在某處。

+0

爲了保留PixelFormat和Dpi我使用我的Temp位圖,然後將PixelData複製到具有正確格式的圖像。 –