Загрузка / Создание изображения в SharpDX в программе .NET - PullRequest
7 голосов
/ 02 марта 2011

Я пытаюсь использовать SharpDX для создания простой лабиринтной 2D-программы с использованием DirectX.

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

Однако я не могу понять, как загрузить существующий файл изображения в класс Bitmap в библиотеке SharpDX или как создать новый такой класс Bitmap с нуля.

Поскольку все классы, как говорят, отображаются непосредственно на типы DirectX, я думаю, это просто означает, что мне нужно больше изучать DirectX, но я надеялся, что где-то был простой пример, который мог бы показать мне, что мне нужно делать.

Если мне нужно создать новое растровое изображение с нуля и нарисовать его, я могу это сделать, нетрудно получить нужные пиксели, но я даже не могу понять эту часть.

Кто-нибудь имеет опыт работы с библиотекой SharpDX и может дать мне несколько советов?

Ответы [ 4 ]

10 голосов
/ 05 марта 2011

Вы должны задать этот вопрос непосредственно на вкладке «Проблема» в проекте Sharpdx, так как я мог бы дать вам быстрый ответ оттуда (вам повезло, что я иногда проверяю его использование из сети;)),Если бы вы спрашивали об этом официально, я мог бы улучшить библиотеку и сохранить запись вашего запроса в базе данных проблем.

Что касается вашей конкретной проблемы, неясно, какой тип DirectX API вы используете.Я предполагаю, что вы используете Direct2D?

Если да, API не существует для прямой загрузки SharpDX.Direct2D1.Bitmap из файла (я добавлю этот метод в API).Я только что загрузил образец растрового изображения , который выполняет это.

/// <summary>
/// Loads a Direct2D Bitmap from a file using System.Drawing.Image.FromFile(...)
/// </summary>
/// <param name="renderTarget">The render target.</param>
/// <param name="file">The file.</param>
/// <returns>A D2D1 Bitmap</returns>
public static Bitmap LoadFromFile(RenderTarget renderTarget, string file)
{
    // Loads from file using System.Drawing.Image
    using (var bitmap = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(file))
    {
        var sourceArea = new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height);
        var bitmapProperties = new BitmapProperties(new PixelFormat(Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied));
        var size = new System.Drawing.Size(bitmap.Width, bitmap.Height);

        // Transform pixels from BGRA to RGBA
        int stride = bitmap.Width * sizeof(int);
        using (var tempStream = new DataStream(bitmap.Height * stride, true, true))
        {
            // Lock System.Drawing.Bitmap
            var bitmapData = bitmap.LockBits(sourceArea, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

            // Convert all pixels 
            for (int y = 0; y < bitmap.Height; y++)
            {
                int offset = bitmapData.Stride*y;
                for (int x = 0; x < bitmap.Width; x++)
                {
                    // Not optimized 
                    byte B = Marshal.ReadByte(bitmapData.Scan0, offset++);
                    byte G = Marshal.ReadByte(bitmapData.Scan0, offset++);
                    byte R = Marshal.ReadByte(bitmapData.Scan0, offset++);
                    byte A = Marshal.ReadByte(bitmapData.Scan0, offset++);
                    int rgba = R | (G << 8) | (B << 16) | (A << 24);
                    tempStream.Write(rgba);
                }

            }
            bitmap.UnlockBits(bitmapData);
            tempStream.Position = 0;

            return new Bitmap(renderTarget, size, tempStream, stride, bitmapProperties);
        }
    }
}

Как вы сказали, SharpDX предоставляет доступ к необработанному низкоуровневому API DirectX (в отличие, например, от XNA, которыйдает более высокий уровень API), поэтому вам определенно необходимо понять, как программировать сырой DirectX, чтобы использовать SharpDX.

0 голосов
/ 27 ноября 2018

И это пример Тома в VB с небольшой модификацией.

Private Function ConvertBitmap(m_renderTarget As RenderTarget, bmp As System.Drawing.Bitmap) As SharpDX.Direct2D1.Bitmap
    Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(
        New System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
        System.Drawing.Imaging.ImageLockMode.ReadOnly,
        System.Drawing.Imaging.PixelFormat.Format32bppPArgb)

    Dim stream As New SharpDX.DataStream(bmpData.Scan0, bmpData.Stride * bmpData.Height, True, False)
    Dim pFormat As New SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied)
    Dim bmpProps As New SharpDX.Direct2D1.BitmapProperties(pFormat)

    Dim Result As New SharpDX.Direct2D1.Bitmap(
        m_renderTarget,
        New SharpDX.Size2(bmp.Width, bmp.Height),
        stream,
        bmpData.Stride,
        bmpProps)

    bmp.UnlockBits(bmpData)

    stream.Dispose()
    bmp.Dispose()

    Return Result
End Function

Предоставляя rendertarget и bitmap в вызове функции, я могу использовать функцию в операторе Lambda, чтобы поместить растровое изображение вкэш ресурсов, который предоставляется в D2dControl с помощью dalance (доступно в NuGet).Кроме того, поскольку мои проекты загружены в качестве ресурсов в моем проекте, я могу просто предоставить их в вызове функции:

Public Sub New()

    ...
    resCache.Add("MainBitmap", Function(t As RenderTarget) ConvertBitmap(t, My.Resources.ProjectUtumno_full))
End Sub

Public Overrides Sub Render(target As RenderTarget)
    target.Clear(New RawColor4(1.0F, 1.0F, 1.0F, 1.0F))

    ...

    target.DrawBitmap(resCache("MainBitmap"), 1.0F, New BitmapInterpolationMode())
end sub
0 голосов
/ 27 ноября 2018

Вот подход Александра в VB:

'/// <summary>
'/// Loads a Direct2D Bitmap from a file using System.Drawing.Image.FromFile(...)
'/// </summary>
'/// <param name="renderTarget">The render target.</param>
'/// <param name="file">The file.</param>
'/// <returns>A D2D1 Bitmap</returns>
Public Shared Function LoadFromFile(renderTarget As RenderTarget, file As String) As SharpDX.Direct2D1.Bitmap

    '// Loads from file using System.Drawing.Image
    Using bitmap As System.Drawing.Bitmap = System.Drawing.Image.FromFile(file)

        Dim sourceArea As New System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height)
        Dim BitmapProperties As New BitmapProperties(New Direct2D1.PixelFormat(DXGI.Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied))
        Dim Size As New System.Drawing.Size(bitmap.Width, bitmap.Height)
        Dim b As Byte
        Dim g As Byte
        Dim r As Byte
        Dim a As Byte
        Dim rgba As Int32
        '// Transform pixels from BGRA to RGBA
        Dim stride As Int32 = bitmap.Width * 4
        Using tempStream As New DataStream(bitmap.Height * stride, True, True)

            '// Lock System.Drawing.Bitmap
            Dim bitmapData As System.Drawing.Imaging.BitmapData = bitmap.LockBits(sourceArea, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppPArgb)

            '// Convert all pixels 
            For y As Int32 = 0 To bitmap.Height - 1

                Dim offset As Int32 = bitmapData.Stride * y
                For x As Int32 = 0 To bitmap.Width - 1

                    '// Not optimized 
                    b = Marshal.ReadByte(bitmapData.Scan0, offset)
                    offset += 1
                    g = Marshal.ReadByte(bitmapData.Scan0, offset)
                    offset += 1
                    r = Marshal.ReadByte(bitmapData.Scan0, offset)
                    offset += 1
                    a = Marshal.ReadByte(bitmapData.Scan0, offset)
                    offset += 1
                    rgba = r Or (g << 8) Or (b << 16) Or (a << 24)
                    tempStream.Write(rgba)
                Next

            Next
            bitmap.UnlockBits(bitmapData)
            tempStream.Position = 0

            Return New Bitmap(renderTarget, New Size2(Size.Width, Size.Height), tempStream, stride, BitmapProperties)
        End Using
    End Using
End Function
0 голосов
/ 14 сентября 2016

Вернувшись, когда я использовал SlimDX, я столкнулся с той же проблемой (загрузка растрового изображения с помощью Direct2D) и нашел аналогичное решение, которое устраняет встроенный цикл и требует немного меньше кода;преобразование его в SharpDX было простым делом.(Хотелось бы сказать вам, где я нашел оригинал, но это были годы, и, видимо, я не документировал источник. Это может быть прямо из образцов SlimDX, насколько я знаю.)

Я ушелпространства имен не повреждены, поэтому вы точно знаете, где определен каждый тип.Кроме того, некоторые параметры (в частности, для PixelFormat) являются гибкими;поэкспериментируйте с ними и используйте все, что вам подходит.

private Bitmap Load(string filename)
{
    System.Drawing.Bitmap bmp = (System.Drawing.Bitmap)System.Drawing.Image.FromFile(filename);

    System.Drawing.Imaging.BitmapData bmpData =
        bmp.LockBits(
            new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
            System.Drawing.Imaging.ImageLockMode.ReadOnly,
            System.Drawing.Imaging.PixelFormat.Format32bppPArgb);

    SharpDX.DataStream stream = new SharpDX.DataStream(bmpData.Scan0, bmpData.Stride * bmpData.Height, true, false);
    SharpDX.Direct2D1.PixelFormat pFormat = new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, AlphaMode.Premultiplied);
    SharpDX.Direct2D1.BitmapProperties bmpProps = new SharpDX.Direct2D1.BitmapProperties(pFormat);

    SharpDX.Direct2D1.Bitmap result =
        new SharpDX.Direct2D1.Bitmap(
            m_renderTarget,
            new SharpDX.Size2(bmp.Width, bmp.Height),
            stream,
            bmpData.Stride,
            bmpProps);

    bmp.UnlockBits(bmpData);

    stream.Dispose();
    bmp.Dispose();

    return result;
}

Как вы можете видеть, он блокирует поток растровых изображений почти так же, как подход Александра (который используется в связанном примере проекта SharpDX), но вместо того, чтобы вручнуюкопируя каждый пиксель, конструктор сам копирует поток за кулисы.Я не сравнивал производительность с методом, предложенным Александром, поэтому я не могу сказать вам, какой метод быстрее, но этот достаточно быстрый для моих целей, и код чистый.

(Извинитеиз-за отсутствия подсветки синтаксиса тег по некоторым причинам разбивает мой фрагмент на разделы.)

...