Как преобразовать поток в D3DImage с помощью SharpDX 4.2.0?

Я хочу отобразить byte[] в формате jpg в D3DImage в приложении WPF с помощью SharpDX 4.2.0.

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

РЕДАКТИРОВАТЬ : Я создал два D3D11.Texture2D, один для записи пикселей и один для совместного использования для d3d9, и он скомпилирован, но на экране ничего не отображается. Надеюсь, кто-нибудь объяснит мне, почему не отображается изображение.

шаг 1. от Stream до SharpDX.Direct3D11.Texture2D

шаг 2. создайте SharpDX.Direct3D11.Texture2Dd3dTexture_Draw и напишите на нем пиксель.

шаг 3. создайте SharpDX.Direct3D11.Texture2D_finalTexture, чтобы поделиться с Direct3D9.Texture

шаг 4. d11dContext.CopyResource(d3dTexture_Draw, _finalTexture);

шаг 5. поделитесь _finalTexture с Direct3D9.Texture

шаг 6. D3DImage.SetBackBufferDirect3D9.Texture поверхность

Я надеюсь получить любую помощь для этого.

РЕДАКТИРОВАТЬ : @Simon Mourier: Ваш ответ отлично работает!

private void LoadBmpToTexture(string filePath)
{
    // Load the JPEG into a Bitmap
    using (System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(filePath))
    {
        SharpDX.Direct3D11.Device device = new SharpDX.Direct3D11.Device(DriverType.Hardware, DeviceCreationFlags.None | DeviceCreationFlags.BgraSupport, SharpDX.Direct3D.FeatureLevel.Level_11_0);
        SharpDX.Direct3D11.DeviceContext d11dContext = device.ImmediateContext;

        byte[] byteArray = ConvertBitmapToByteArray(bitmap);
        MemoryStream memoryStream = new MemoryStream(byteArray);                
        using (var imagingFactory = new SharpDX.WIC.ImagingFactory2())
        {
            var decoder = new SharpDX.WIC.BitmapDecoder(imagingFactory, memoryStream, DecodeOptions.CacheOnLoad);
            var frame = decoder.GetFrame(0);
            var formatConverter = new FormatConverter(imagingFactory);
            formatConverter.Initialize(frame, SharpDX.WIC.PixelFormat.Format32bppPBGRA);

            var width = formatConverter.Size.Width;
            var height = formatConverter.Size.Height;

            var textureDesc = new Texture2DDescription
            {
                Width = width,
                Height = height,
                MipLevels = 1,
                ArraySize = 1,
                Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                SampleDescription = new SampleDescription(1, 0),
                Usage = ResourceUsage.Dynamic,
                BindFlags = BindFlags.ShaderResource,
                CpuAccessFlags = CpuAccessFlags.Write,

            };

            var d3dTexture_Draw = new Texture2D(device, textureDesc);

            // Copy data to Texture2D
            var dataBox = d11dContext.MapSubresource(d3dTexture_Draw, 0, MapMode.WriteDiscard, SharpDX.Direct3D11.MapFlags.None);
            using (var wicStream = new DataStream(dataBox.DataPointer, width * height * 4, true, true))
            {
                formatConverter.CopyPixels(width * 4, wicStream);
            }
            d11dContext.UnmapSubresource(d3dTexture_Draw, 0);


            var final_descriptor = new Texture2DDescription()
            {
                Width = (int)img.Width,
                Height = (int)img.Height,
                ArraySize = 1,
                BindFlags = BindFlags.RenderTarget | BindFlags.ShaderResource,
                Usage = ResourceUsage.Default,
                CpuAccessFlags = CpuAccessFlags.None,
                Format = SharpDX.DXGI.Format.B8G8R8A8_UNorm,
                MipLevels = 1,
                OptionFlags = ResourceOptionFlags.Shared,
                SampleDescription = new SampleDescription(1, 0)
            };

            Texture2D _finalTexture = new Texture2D(device, final_descriptor);

            d11dContext.CopyResource(d3dTexture_Draw, _finalTexture);

            SharpDX.Direct3D9.Direct3DEx d9context = new SharpDX.Direct3D9.Direct3DEx();
            SharpDX.Direct3D9.Device d9device = new SharpDX.Direct3D9.Device(d9context,
                                                                0,
                                                                DeviceType.Hardware,
                                                                IntPtr.Zero,
                                                                CreateFlags.HardwareVertexProcessing,
                                                                new SharpDX.Direct3D9.PresentParameters()
                                                                {
                                                                    Windowed = true,
                                                                    SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard,
                                                                    DeviceWindowHandle = new WindowInteropHelper(this).Handle,
                                                                    PresentationInterval = PresentInterval.Immediate,
                                                                });

            IntPtr renderTextureHandle = _finalTexture.QueryInterface<SharpDX.DXGI.Resource>().SharedHandle;

            SharpDX.Direct3D9.Texture d9texture = new SharpDX.Direct3D9.Texture(d9device,
                                                                   _finalTexture.Description.Width,
                                                                   _finalTexture.Description.Height,
                                                                   1,
                                                                   SharpDX.Direct3D9.Usage.RenderTarget,
                                                                   SharpDX.Direct3D9.Format.A8R8G8B8,
                                                                   Pool.Default,
                                                                   ref renderTextureHandle);
            
            d3dImage = new D3DImage();
            d3dImage.Lock();
            
            d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, d9texture.GetSurfaceLevel(0).NativePointer, true);

            //Image d3dImage : Width=720, Height=370
            d3dImage.AddDirtyRect(new Int32Rect(0, 0, 720, 370));
            d3dImage.Unlock();
            img.Source= d3dImage;
        }
    }
}

Почему ваш код содержит код D3D11 и DXGI, а D3DImage ожидает указатель на поверхность D3D9? Вы можете получить поверхность из вызова LockRect CreateOffscreenPlainSurface d3d9Device, записать на нее биты растрового изображения, вызвать UnlockRect и передать их в SetBackBuffer. Но это также зависит от входного потока, что именно?

Simon Mourier 02.08.2024 12:39

@SimonMourier Я новичок в DirectX и SharpDX. Поэтому я следил за информацией из Google и GPT. Спасибо за ваше руководство, я попробую.

Steve Park 06.08.2024 07:52

Вам следует опубликовать проект воспроизведения где-нибудь.

Simon Mourier 06.08.2024 08:08

Это здесь -> github.com/NuclearPark/D3DImage-with-SharpDX

Steve Park 06.08.2024 08:24
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вот решение, которое использует только WIC и DirectX 9:

public partial class MainWindow : Window
{
    private readonly D3DImage _d3dImage = new();

    // you can keep the device if you want to use it
    private readonly SharpDX.Direct3D9.Device _device;

    public MainWindow()
    {
        InitializeComponent();
        Loaded += (s, e) => LoadJpegToTexture(@"sample.bmp");

        var hwnd = new WindowInteropHelper(this).EnsureHandle();
        using var context = new SharpDX.Direct3D9.Direct3D();
        _device = new SharpDX.Direct3D9.Device(context,
            0,
            SharpDX.Direct3D9.DeviceType.Hardware,
            hwnd,
            SharpDX.Direct3D9.CreateFlags.HardwareVertexProcessing,
            new SharpDX.Direct3D9.PresentParameters()
            {
                Windowed = true,
                SwapEffect = SharpDX.Direct3D9.SwapEffect.Discard,
                DeviceWindowHandle = hwnd,
                PresentationInterval = SharpDX.Direct3D9.PresentInterval.Immediate,
            });

        img.Source = _d3dImage;
    }

    private void LoadJpegToTexture(string filePath)
    {
        using var imagingFactory = new SharpDX.WIC.ImagingFactory2();
        using var decoder = new SharpDX.WIC.BitmapDecoder(imagingFactory, filePath, SharpDX.WIC.DecodeOptions.CacheOnDemand);
        using var frame = decoder.GetFrame(0);

        // depending on the image's pixel format, you must convert the frame
        // to match DirectX 9 RGBA surface format
        using var converter = new SharpDX.WIC.FormatConverter(imagingFactory);
        converter.Initialize(frame, SharpDX.WIC.PixelFormat.Format32bppBGRA);

        // create a render target surface
        using var surface = SharpDX.Direct3D9.Surface.CreateRenderTarget(_device,
            frame.Size.Width,
            frame.Size.Height,
            SharpDX.Direct3D9.Format.A8R8G8B8,
            SharpDX.Direct3D9.MultisampleType.None,
            0,
            true
            );

        // copy pixels from WIC to surface
        var rc = surface.LockRectangle(SharpDX.Direct3D9.LockFlags.None);
        converter.CopyPixels(rc.Pitch, rc.DataPointer, frame.Size.Height * rc.Pitch);
        surface.UnlockRectangle();

        _d3dImage.Lock();
        _d3dImage.SetBackBuffer(D3DResourceType.IDirect3DSurface9, surface.NativePointer, true);
        _d3dImage.AddDirtyRect(new Int32Rect(0, 0, frame.Size.Width, frame.Size.Height));
        _d3dImage.Unlock();
    }
}

Удивительно, что вы сэкономили мои 100++ часов. Глубоко оценен. Будьте здоровы. Как только я получу 15 репутации, я проголосую за ваш ответ.

Steve Park 06.08.2024 12:19

@Клеменс: Хорошая мысль, Клеменс.

Steve Park 06.08.2024 13:04

Другие вопросы по теме