【问题标题】:Converting System.drawing to SharpDX.direct 2D1将 System.drawing 转换为 SharpDX.direct 2D1
【发布时间】:2017-06-20 15:42:26
【问题描述】:

我正在开发一个可以根据用户设置在 CPU 或 GPU 上绘图的图形应用程序。为了利用 CPU,我将 GDI+ 技术与 System.Drawing 组件一起使用。要在 GPU 上绘图,我想使用 SharpDX.Direct2D1(因为我使用的是 c#)。

我创建了一个 DrawingContext 抽象类,它实现了 Graphics 类的每个绘图功能(接收 System.Drawing.Brush、System.Drawing.Rectangle 等...作为参数)并将它们重新实现到它的派生类(CPUDrawingContext)中。现在,我有一个必须覆盖所有这些方法的 GPUDrawingContext 类,但由于参数来自 System.Drawing 类型,我需要将它们转换为 sharpDX 组件,速度非常快,所以我们看不到区别。

在这里看一个小例子:我只放了一部分代码,所以你可以看到这个概念。

绘图上下文

Public abstract class DrawingContext {
//System.drawing.Bitmap, System.Drawing.RectangleF
Public asbstract DrawImage(Bitmap b, RectangleF dest, RectangleF source,GraphicsUnit g);
//System.Drawing.Brush
Public abstract DrawRectangle(Brush b, Rectangle rect);


}

CPUDrawingContext:使用graphicContext As Graphics在屏幕上渲染

Public  class CPUDrawingContext{
  //System.drawing.Bitmap, System.Drawing.RectangleF
  Public override DrawImage(Bitmap b, RectangleF dest, RectangleF source,GraphicsUnit g);
  //System.Drawing.Brush
  Public override DrawRectangle(Brush b, Rectangle rect){
      graphicContext.Rectangle(b,rect);
  }
  Public override DrawImage(Bitmap b, RectangleF dest, RectangleF source, GraphicsUnit g) {
      graphicContext.DrawImage(b,dest,source,g);
  }
}

GPUDrawingContext : 使用 renderTarger 作为 RenderTarget 在屏幕上渲染

Public class GPUDrawingContext {
   //System.drawing.Bitmap, System.Drawing.RectangleF
  Public override DrawImage(Bitmap b, RectangleF dest, RectangleF  source,GraphicsUnit g);
  //System.Drawing.Brush
  Public override DrawRectangle(Brush b, Rectangle rect){
      //convert b and rect to fit sharpDX component
      renderTarget.DrawRectangle(b,rect);
   }
  Public override DrawImage(Bitmap b, RectangleF dest, RectangleF source, GraphicsUnit g) {
      //(convert b,dest,source and g to fit sharpDX component)
      renderTarget.DrawImage(b,dest,source,g);
   }
 }

我已经在 GPUDrawingContext 中注释了我在绘制之前需要转换的区域。

我的问题是,是否有可能非常快地做到这一点,所以我们不会注意到(比如少于 10 毫秒的转换)。

由于我的应用程序需要绘制位图,我需要非常快地将 System.Drawing.Bitmap 转换为 SharpDX.Direct2D1.Bitmap,但我注意到SharpDX 位图似乎与 System.Drawing.Bitmap 并不真正兼容。

【问题讨论】:

    标签: c# winforms sharpdx


    【解决方案1】:

    这就是我如何将 System.Drawing.Bitmap 转换为 SharpDX.Direct2d1.Bitmap。

    Dim bmpData As BitmapData = m_Bitmap.LockBits(New System.Drawing.Rectangle(0, 0, m_Bitmap.Width, m_Bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, m_Bitmap.PixelFormat)
    
      Dim bgraArray As Byte() = New Byte(bmpData.Width * bmpData.Height * 4 - 1) {}
    
      Dim scan As IntPtr = bmpData.Scan0
      Marshal.Copy(scan, bgraArray, 0, (bmpData.Width * bmpData.Height) * 4)
    
      Dim rgbaarray As Byte() = New Byte(bmpData.Width * bmpData.Height * 4 - 1) {}
    
      Parallel.For(0, 4, Sub(range)
                            For i As Integer = range * bmpData.Height / 4 To bmpData.Height / 4 * (range + 1) - 1
                               Dim offset As Integer = i * bmpData.Width * 4
                               For j As Integer = 0 To bmpData.Width * 4 - 1 Step 4
                                  rgbaarray(offset + j) = bgraArray(offset + j + 2)
                                  rgbaarray(offset + j + 1) = bgraArray(offset + j + 1)
                                  rgbaarray(offset + j + 2) = bgraArray(offset + j)
                                  rgbaarray(offset + j + 3) = bgraArray(offset + j + 3)
                               Next
                            Next
                         End Sub)
    
      Dim stream As DataStream = New DataStream(bmpData.Height * bmpData.Width * 4, True, True)
      stream.WriteRange(rgbaarray)
      stream.Position = 0
      m_sharpDXbitmap = New SharpDX.Direct2D1.Bitmap(deviceContext, New Size2(m_Bitmap.Width, m_Bitmap.Height), stream, bmpData.Width * 4, bitmapProperties)
      m_Bitmap.UnlockBits(bmpData)
    
      stream.Dispose()
    

    但是,这不是 10 毫秒,而是 120 毫秒。我为保持我想要的抽象所做的是创建一个包含两个位图的 CustomBitmap 类,并且在第一次绘制调用时,如果尚未转换,则只转换一次,依此类推未来的抽奖电话,这将是即时的。这是我的 CustomBitmap 类:

    Imports System.Drawing.Imaging
    Imports System.Reflection
    Imports SharpDX
    Imports SharpDX.Direct2D1
    Imports System.Runtime.InteropServices
    Imports Synergx.Common.Drawing
    Imports System.Collections.Concurrent
    Imports System.Threading.Tasks
    
    Public Class CustomBitmap
    
       Private bitmapProperties As BitmapProperties = New BitmapProperties(New SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.R8G8B8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Ignore))
    
       Public Property Bitmap As System.Drawing.Bitmap
          Get
             Return m_Bitmap
          End Get
          Set(value As System.Drawing.Bitmap)
             m_Bitmap = value
          End Set
       End Property
    
       Private m_Width As Integer
       Private m_Height As Integer
       Private m_Bitmap As System.Drawing.Bitmap
       Private m_sharpDXbitmap As SharpDX.Direct2D1.Bitmap = Nothing
    
       Public ReadOnly Property Width As Integer
          Get
             Return m_Width
          End Get
       End Property
    
       Public ReadOnly Property Height As Integer
          Get
             Return m_Height
          End Get
       End Property
    
       Public ReadOnly Property GPUBitmap As SharpDX.Direct2D1.Bitmap
          Get
             Return m_sharpDXbitmap
          End Get
       End Property
    
       Public Sub New(bitmap As System.Drawing.Bitmap)
          Me.Bitmap = bitmap
          m_Width = bitmap.Width
          m_Height = bitmap.Height
       End Sub
    
       Friend Sub GenerateSharpDXBitmap(deviceContext As SharpDX.Direct2D1.DeviceContext)
    
          If (m_Bitmap.PixelFormat = Imaging.PixelFormat.Format8bppIndexed) Then
             GenerateSharpDXBitmap8bpp(deviceContext)
          ElseIf (m_Bitmap.PixelFormat = Imaging.PixelFormat.Format32bppArgb) Then
             GenerateSharpDXBitmap32argp(deviceContext)
          End If
    
       End Sub
    
       Private Sub GenerateSharpDXBitmap8bpp(deviceContext As SharpDX.Direct2D1.DeviceContext)
    
          Dim bmpData As BitmapData = m_Bitmap.LockBits(New System.Drawing.Rectangle(0, 0, m_Bitmap.Width, m_Bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, m_Bitmap.PixelFormat)
    
          Dim integerArray As Integer()
          ReDim integerArray(bmpData.Height * bmpData.Width - 1)
    
          Parallel.For(0, 4, Sub(range)
                                Dim scan As IntPtr = bmpData.Scan0
    
                                For i As Integer = 0 To bmpData.Height * range / 4 - 1 - 1
                                   scan += bmpData.Stride
                                Next
    
                                For y As Integer = bmpData.Height * range / 4 To bmpData.Height * (range + 1) / 4 - 1
                                   Dim bytes As Byte() = New Byte(bmpData.Width - 1) {}
                                   Marshal.Copy(scan, bytes, 0, bmpData.Width)
    
                                   For x As Integer = 0 To bytes.Length - 1
                                      Dim B As Integer = bytes(x)
                                      Dim rgba As Integer = B Or (B << 8) Or (B << 16) Or (B << 24)
                                      integerArray(x + y * bmpData.Width) = rgba
                                   Next
                                   scan += bmpData.Stride
    
                                Next
                             End Sub)
    
          Dim stream As DataStream = New DataStream(bmpData.Height * bmpData.Width * 4, True, True)
          stream.WriteRange(integerArray)
          stream.Position = 0
          m_sharpDXbitmap = New SharpDX.Direct2D1.Bitmap(deviceContext, New Size2(m_Bitmap.Width, m_Bitmap.Height), stream, bmpData.Width * 4, bitmapProperties)
          m_Bitmap.UnlockBits(bmpData)
    
          stream.Dispose()
    
       End Sub
    
       Private Sub GenerateSharpDXBitmap32argp(deviceContext As SharpDX.Direct2D1.DeviceContext)
          Dim bmpData As BitmapData = m_Bitmap.LockBits(New System.Drawing.Rectangle(0, 0, m_Bitmap.Width, m_Bitmap.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, m_Bitmap.PixelFormat)
    
          Dim bgraArray As Byte() = New Byte(bmpData.Width * bmpData.Height * 4 - 1) {}
    
          Dim scan As IntPtr = bmpData.Scan0
          Marshal.Copy(scan, bgraArray, 0, (bmpData.Width * bmpData.Height) * 4)
    
          Dim rgbaarray As Byte() = New Byte(bmpData.Width * bmpData.Height * 4 - 1) {}
    
          Parallel.For(0, 4, Sub(range)
                                For i As Integer = range * bmpData.Height / 4 To bmpData.Height / 4 * (range + 1) - 1
                                   Dim offset As Integer = i * bmpData.Width * 4
                                   For j As Integer = 0 To bmpData.Width * 4 - 1 Step 4
                                      rgbaarray(offset + j) = bgraArray(offset + j + 2)
                                      rgbaarray(offset + j + 1) = bgraArray(offset + j + 1)
                                      rgbaarray(offset + j + 2) = bgraArray(offset + j)
                                      rgbaarray(offset + j + 3) = bgraArray(offset + j + 3)
                                   Next
                                Next
                             End Sub)
    
          Dim stream As DataStream = New DataStream(bmpData.Height * bmpData.Width * 4, True, True)
          stream.WriteRange(rgbaarray)
          stream.Position = 0
          m_sharpDXbitmap = New SharpDX.Direct2D1.Bitmap(deviceContext, New Size2(m_Bitmap.Width, m_Bitmap.Height), stream, bmpData.Width * 4, bitmapProperties)
          m_Bitmap.UnlockBits(bmpData)
    
          stream.Dispose()
       End Sub
    
       Public Sub Dispose()
          If Bitmap IsNot Nothing Then
             m_Bitmap.Dispose()
             m_Bitmap = Nothing
          End If
          If m_sharpDXbitmap IsNot Nothing Then
             m_sharpDXbitmap.Dispose()
             m_sharpDXbitmap = Nothing
          End If
       End Sub
    
    End Class
    

    该类包含 2 种不同的方法,可以根据图像的原始 PixelFormat 分离为灰度颜色或 32bpp。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-29
      • 2018-02-28
      • 1970-01-01
      • 2019-10-08
      • 1970-01-01
      • 2012-05-10
      • 2014-01-17
      • 1970-01-01
      相关资源
      最近更新 更多