Создание текстур параллельно - PullRequest
0 голосов
/ 04 июля 2018

Я работаю с множеством программно сгенерированных растровых изображений, которые мне нужно преобразовать в Texture2D, чтобы они могли отображаться в Monogame

Это то, что я называю в обычном цикле, проблема в том, что он очень медленный.

Function BitmapToTexture2D(Bitmap As Drawing.Bitmap, Device As GraphicsDevice) As Texture2D
    Dim Result As Texture2D = Nothing
    Using MemoryStream As MemoryStream = New MemoryStream
        Bitmap.Save(MemoryStream, ImageFormat.Bmp)
        MemoryStream.Seek(0, SeekOrigin.Begin)
        Result = Texture2D.FromStream(Device, MemoryStream)
    End Using

    Return Result
End Function

Если бы я мог создать Texture2D без необходимости указывать GraphicsDevice, это было бы идеально.

Обновление 1: Пытаясь обойти эту проблему, я попытался избавиться от необходимости использовать MemoryStream для повышения производительности.

Function BitmapToTexture2D(Bitmap As Drawing.Bitmap, Device As GraphicsDevice) As Texture2D
    Dim Result As New Texture2D(Device, Bitmap.Size.Width, Bitmap.Size.Height)
    Result.SetData(BitmapToColorArrayMonogame(Bitmap))

    Return Result
End Function

Function BitmapToColorArrayMonogame(Bitmap As Drawing.Bitmap) As Color()
    Dim Color() As Color = New Color(Bitmap.Size.Width * Bitmap.Size.Height - 1) {}

    For X As Integer = 0 To (Bitmap.Size.Width - 1)
        For Y As Integer = 0 To (Bitmap.Size.Height - 1)
            Color((Bitmap.Size.Width * Y) + X) = SystemColorToMonogame(Bitmap.GetPixel(X, Y))
        Next
    Next
    Return Color
End Function

Function SystemColorToMonogame(Color As System.Drawing.Color) As Color
    Return New Microsoft.Xna.Framework.Color(Color.R, Color.G, Color.B, Color.A)
End Function

Результаты:

  • Non-MemoryStream: 4659
  • MemoryStream: 252

в миллисекундах.

MemoryStream значительно быстрее, чем обходить его. Тем не менее, я бы предпочел, если бы я мог сделать это в фоновом режиме, параллельно.

Обновление 2: С адаптированным здесь кодом

Function BitmapToTexture2DLockBits(Bitmap As Drawing.Bitmap, Device As GraphicsDevice) As Texture2D
    Dim Result As New Texture2D(Device, Bitmap.Size.Width, Bitmap.Size.Height)
    Dim Rectangle As New Drawing.Rectangle(0, 0, Bitmap.Width, Bitmap.Height)
    Dim Data As BitmapData = Bitmap.LockBits(Rectangle, ImageLockMode.ReadWrite, Bitmap.PixelFormat)
    Dim NumBytes As Integer = (Data.Stride * Bitmap.Height)
    Dim Bytes As Byte() = New Byte(NumBytes - 1) {}
    System.Runtime.InteropServices.Marshal.Copy(Data.Scan0, bytes, 0, numBytes)
    Bitmap.UnlockBits(data)
    Result.SetData(Bytes)

    Return Result
End Function

Результаты:

  • SetData From Array: 4371
  • MemoryStream: 221
  • LockBits: 63

Значительно быстрее, но все же не параллельно. Он не может быть параллельным, потому что GraphicsDevice должен использоваться для создания Texture2D, и при параллельном вызове он блокирует все приложение.

Должен быть какой-то способ создать Texture2D без использования GraphicsDevice.

Примечание: Дальнейшее тестирование показывает, что вы не можете установить SetData для текстуры параллельно, она блокируется и параллельный цикл никогда не заканчивается.

...