Я разрабатываю приложение. NET WinForms, и мне нужно масштабировать множество больших изображений и отображать их как маленькие значки в форме. У меня проблемы с производительностью особенно на указанных c машинах. Профили показывают, что больше всего времени занимает GDI + при масштабировании этих изображений. Таким образом, моя цель сейчас - использовать SharpDX для масштабирования этих изображений с помощью Direct2D и рисовать их с помощью GDI + после этого как есть. Теперь у меня есть тестовый класс, в котором я генерирую устройства и контекст только один раз. Затем я передаю источник и цель. NET Растровые изображения в метод Scale.
Public Sub ScaleImage(pBaseImage As System.Drawing.Bitmap, pTargetImage As System.Drawing.Bitmap)
FillSourceBitmap(pBaseImage)
Dim cropEffect = New d2.Effects.Crop(d2dContext)
cropEffect.SetInput(0, d2SourceBitmap, True)
cropEffect.Rectangle = New Mathematics.Interop.RawVector4(0, 0, pBaseImage.Width, pBaseImage.Height)
Dim scaleEffect = New d2.Effects.Scale(d2dContext)
scaleEffect.SetInput(0, cropEffect.Output, True)
scaleEffect.ScaleAmount = New SharpDX.Mathematics.Interop.RawVector2(pTargetImage.Width / pBaseImage.Width, pTargetImage.Height / pBaseImage.Height)
Dim d2TargetBitmapProps = New d2.BitmapProperties1(d2PixelFormat, 96, 96, d2.BitmapOptions.Target)
Dim d2TargetBitmap = New d2.Bitmap1(d2dContext, New Size2(pTargetImage.Width, pTargetImage.Height), d2TargetBitmapProps)
d2dContext.Target = d2TargetBitmap
d2dContext.BeginDraw()
d2dContext.DrawImage(scaleEffect,)
d2dContext.EndDraw()
CopyBitmapFromDxToGDI(d2TargetBitmap, pTargetImage)
End Sub
Private Sub FillSourceBitmap(bmp As Drawing.Bitmap)
Dim bmpData As Imaging.BitmapData = bmp.LockBits(New Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), Imaging.ImageLockMode.ReadWrite, Imaging.PixelFormat.Format32bppPArgb)
d2SourceBitmap.CopyFromMemory(bmpData.Scan0, bmpData.Stride,
New Mathematics.Interop.RawRectangle(0, 0, bmpData.Width, bmpData.Height))
bmp.UnlockBits(bmpData)
End Sub
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
Полный код можно найти здесь https://github.com/Drreamer/Direct2DImageProcessing
Теперь код работает, но все еще недостаточно быстро. Профиль показывает, что большая часть временного кода не работает, но выполняются некоторые другие операции: введите описание изображения здесь
Вы можете видеть, что рендеринг одного изображения занимает 10 мс. После этого другой поток приложения работает в течение 10 мс, а после этого приложение ничего не делает в течение 20 мс. Кто-нибудь знает, в чем причина проблемы и как нужно переписать решение, чтобы решить проблему?