如何从SharpDXDirect2D复制图像到.NET位图?

问题描述 投票:-1回答:1

我开发了一个.NET WinForms应用程序,需要缩放大量的大图片,并将其作为小图标显示在表单上。我有一个性能问题,特别是在特定的机器上。因此,我现在的目标是使用SharpDX使用Direct2D来缩放这些图像。不知何故,现在图像已经被缩放了,但我不能将图像从DirectX位图复制到.NET位图。

Private Sub CopyBitmapFromDxToGDI(bitmap As d2.Bitmap1, bmp As Drawing.Bitmap)
   Dim d2dBitmapProps2 = New d2.BitmapProperties1(d2PixelFormat, 96, 96, BitmapOptions.CpuRead Or BitmapOptions.CannotDraw  )
   Dim d2dRenderTarget2 = New d2.Bitmap1(d2dContext, New Size2(bmp.Width, bmp.Height), d2dBitmapProps2)
   d2dRenderTarget2.CopyFromRenderTarget(d2dContext)
   Dim surface = d2dRenderTarget2.Surface
   Dim dataStream As DataStream = Nothing
   surface.Map(dxgi.MapFlags.Read, dataStream)
   Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(
      New System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
      System.Drawing.Imaging.ImageLockMode.ReadWrite,
      System.Drawing.Imaging.PixelFormat.Format32bppPArgb)

   Dim offset = 3
   Debug.WriteLine($"({surface.Description.Width}, {surface.Description.Height})")
   For y As Integer = 0 To surface.Description.Height - 1         
      For x As Integer = 0 To surface.Description.Width -1         
         Dim b As Byte = dataStream.Read(Of Byte)()
         Dim g As Byte = dataStream.Read(Of Byte)()
         Dim r As Byte = dataStream.Read(Of Byte)()
         Dim a As Byte = dataStream.Read(Of Byte)()            

         Marshal.WriteByte(bmpData.Scan0, offset, a)
         offset += 1
         Marshal.WriteByte(bmpData.Scan0, offset, r)
         offset += 1
         Marshal.WriteByte(bmpData.Scan0, offset, g)
         offset += 1
         Marshal.WriteByte(bmpData.Scan0, offset, b)
         offset += 1
      Next
   Next
   bmp.UnlockBits(bmpData)
   surface.Unmap()
End Sub

代码相当简单。我创建了一个新的允许CPU访问的位图,从它那里得到DataStream,然后将这些数据逐字节写入.NET位图。然而,这段代码大部分都不能工作。只有当目标图像有特定大小时,它才能正确地渲染图像。当目标图像有特定大小时,它就会以AccessViolationException崩溃。在特定大小的情况下,它的渲染很奇怪。enter image description here

你知道我在代码中遗漏了什么吗?

.net vb.net winforms sharpdx direct2d
1个回答
0
投票

为了解决这个问题,有必要使用dataRectangle.Pitch计算内存流中每个像素的位置。下面的代码现在可以正常工作。

Private Sub CopyBitmapFromDxToGDI(bitmap As d2.Bitmap1, bmp As Drawing.Bitmap)
   Dim d2TempBitmapProps = New d2.BitmapProperties1(d2PixelFormat, 96, 96, BitmapOptions.CpuRead Or BitmapOptions.CannotDraw)
   Dim d2TempBitmap = New d2.Bitmap1(d2dContext, New Size2(bmp.Width, bmp.Height), d2TempBitmapProps)      
   d2TempBitmap.CopyFromRenderTarget(d2dContext)

   Dim surface = d2TempBitmap.Surface
   Dim dataStream As DataStream = Nothing
   Dim dataRectangle As DataRectangle = surface.Map(dxgi.MapFlags.Read, dataStream)
   Dim bmpData As Imaging.BitmapData = bmp.LockBits(New Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppPArgb)

   Dim offset = bmpData.Reserved
   Dim buffer(4) As Byte
   For y As Integer = 0 To surface.Description.Height - 1
      For x As Integer = 0 To surface.Description.Width - 1

         dataStream.Seek((y * dataRectangle.Pitch) + (x * 4), SeekOrigin.Begin)
         dataStream.Read(buffer, 0, 4)           

         Marshal.WriteByte(bmpData.Scan0, offset, buffer(3))            
         Marshal.WriteByte(bmpData.Scan0, offset+1, buffer(0))
         Marshal.WriteByte(bmpData.Scan0, offset+2, buffer(1))
         Marshal.WriteByte(bmpData.Scan0, offset+3, buffer(2))
         offset += 4
      Next
   Next
   bmp.UnlockBits(bmpData)
   surface.Unmap()
   dataStream.Dispose()
   d2TempBitmap.Dispose()
End Sub
© www.soinside.com 2019 - 2024. All rights reserved.