2016-05-08 27 views
1

にSlimDX.Direct3D11にTexture2Dを変換すると、このように非常に高速に動作します: http://www.rolandk.de/index.php?option=com_content&view=article&id=65:bitmap-from-texture-d3d11&catid=16:blog&Itemid=10純ビットマップSlimDxに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; 
} 

速い方法はありますか?誰も助けてくださいすることができ

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

しかしDataRectangleあり、正確に8倍以上のデータを、私は私でDataStreamに必要があります。私はこのような、非常に試してみましたか? データのコピーバックには、計算時間全体の約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

私が使用しているコンバータはこれです:私は、DPIが72であることに問題があるといないよしかし

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

私のプログラムで使っているBitmapSourceのようなものです。それがいくつか役立つことを願っています

また、SlimDXを使用しています。

WPFビットマップ変換は、導入からかなりの頭痛です。安全でないコードとロックビットに入ることによって最大速度を得るには、おそらくPbgraとbgraからrgbaへの変換が必要になるでしょう。私は通常、多くのプログラムでBitmapSourceに変換するために古いDrawing Bitmapに戻ります。このスニペットは、私の計算シェーダとの間で正しい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異なるPixelFormatsためするLockBitsとコンバージョンをより細かく制御を有しています。古いCreateBitmap関数とDIBは、コンバージョンにもHBITMAPを使用します。

スピードのもう一つのボトルネックは、Texture2D.ToStream()ルーチンにあると思います。これらのImageFileFormat.Png、ImageFileFormat.Bmp、ImageFileFormat.JpgなどSlimDXはTexture2Dにコピー機能を追加していないため、DX11にはその部分があります。

+0

ピクセルフォーマットとDPIを維持するために私は私の一時ビットマップを使用していますし、正しいフォーマットで画像にピクセルデータをコピーします。 –

関連する問題