Reading Datastream sharpDX Error all values are 0

白昼怎懂夜的黑 提交于 2019-12-11 07:59:16

问题


I followed this solution for my project : How to create bitmap from Surface (SharpDX)

I don't have enough reputation to comment so I'm opening a new question here.

My project is basically in Direct 2D, I have a Surface buffer, a swapchain. I want to put my buffer into a datastream and reads it's value to put it into a bitmap and save it on disk ( like a screen capture), but my code won't work since all the bytes values are 0 (which is black) and this doesn't make sense since my image is fully white with a bit of blue.

Here is my code :

SwapChainDescription description = new SwapChainDescription()
     {
        ModeDescription = new ModeDescription(this.Width, this.Height, new Rational(60, 1), Format.B8G8R8A8_UNorm),
        SampleDescription = new SampleDescription(1, 0),
        Usage = Usage.RenderTargetOutput,
        BufferCount = 1,
        SwapEffect = SwapEffect.Discard,
        IsWindowed = true,
        OutputHandle = this.Handle
     };

     Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.Debug | DeviceCreationFlags.BgraSupport, description, out device, out swapChain);

     SharpDX.DXGI.Device dxgiDevice = device.QueryInterface<SharpDX.DXGI.Device>();
     SharpDX.DXGI.Adapter dxgiAdapter = dxgiDevice.Adapter;

     SharpDX.Direct2D1.Device d2dDevice = new SharpDX.Direct2D1.Device(dxgiDevice);
     d2dContext = new SharpDX.Direct2D1.DeviceContext(d2dDevice, SharpDX.Direct2D1.DeviceContextOptions.None);
     SharpDX.Direct3D11.DeviceContext d3DeviceContext = new SharpDX.Direct3D11.DeviceContext(device);




     properties = new BitmapProperties(new SharpDX.Direct2D1.PixelFormat(SharpDX.DXGI.Format.B8G8R8A8_UNorm, SharpDX.Direct2D1.AlphaMode.Premultiplied),
          96, 96);

     Surface backBuffer = swapChain.GetBackBuffer<Surface>(0);
     d2dTarget = new SharpDX.Direct2D1.Bitmap(d2dContext, backBuffer, properties);

     d2dContext.Target = d2dTarget;

     playerBitmap = this.LoadBitmapFromContentFile(@"C:\Users\ndesjardins\Desktop\wave.png");

     //System.Drawing.Bitmap bitmapCanva = new System.Drawing.Bitmap(1254, 735);

     d2dContext.BeginDraw();
     d2dContext.Clear(SharpDX.Color.White);
     d2dContext.DrawBitmap(playerBitmap, new SharpDX.RectangleF(0, 0, playerBitmap.Size.Width, playerBitmap.Size.Height), 1f, SharpDX.Direct2D1.BitmapInterpolationMode.NearestNeighbor);
     SharpDX.Direct2D1.SolidColorBrush brush = new SharpDX.Direct2D1.SolidColorBrush(d2dContext, SharpDX.Color.Green);
     d2dContext.DrawRectangle(new SharpDX.RectangleF(200, 200, 100, 100), brush);
     d2dContext.EndDraw();

     swapChain.Present(1, PresentFlags.None);


     Texture2D backBuffer3D = backBuffer.QueryInterface<SharpDX.Direct3D11.Texture2D>();

     Texture2DDescription desc = backBuffer3D.Description;
     desc.CpuAccessFlags = CpuAccessFlags.Read;
     desc.Usage = ResourceUsage.Staging;
     desc.OptionFlags = ResourceOptionFlags.None;
     desc.BindFlags = BindFlags.None;

     var texture = new Texture2D(device, desc);

     d3DeviceContext.CopyResource(backBuffer3D, texture);

     byte[] data = null;
     using (Surface surface = texture.QueryInterface<Surface>())
     {
        DataStream dataStream;
        var map = surface.Map(SharpDX.DXGI.MapFlags.Read, out dataStream);
        int lines = (int)(dataStream.Length / map.Pitch);
        data = new byte[surface.Description.Width * surface.Description.Height * 4];

        dataStream.Position = 0;
        int dataCounter = 0;
        // width of the surface - 4 bytes per pixel.
        int actualWidth = surface.Description.Width * 4;
        for (int y = 0; y < lines; y++)
        {
           for (int x = 0; x < map.Pitch; x++)
           {
              if (x < actualWidth)
              {
                 data[dataCounter++] = dataStream.Read<byte>();
              }
              else
              {
                 dataStream.Read<byte>();
              }
           }
        }
        dataStream.Dispose();
        surface.Unmap();

        int width = surface.Description.Width;
        int height = surface.Description.Height;
        byte[] bytewidth = BitConverter.GetBytes(width);
        byte[] byteheight = BitConverter.GetBytes(height);

        Array.Copy(bytewidth, 0, data, 0, 4);
        Array.Copy(byteheight, 0, data, 4, 4);

     }

Do you guys have any idea why the byte array that is returned at the end is full of 0 since it should be mostly 255? All I did in my backbuffer was to draw a bitmap image and a rectangle form. Array.Copy is to add the width and height header to the byte array, therefore I could create a bitmap out of it.


回答1:


I answered in a comment but formatting is horrible so apologies!

https://gamedev.stackexchange.com/a/112978/29920 This looks promising but as you said in reply to mine, this was some time ago and I'm pulling this out of thin air, if it doesn't work either someone with more current knowledge will have to answer or I'll have to grab some source code and try myself.

SharpDX.Direct2D1.Bitmap dxbmp = new SharpDX.Direct2D1.Bitmap(renderTarget, 
new SharpDX.Size2(bmpWidth, bmpHeight), new 
BitmapProperties(renderTarget.PixelFormat));
dxbmp.CopyFromMemory(bmpBits, bmpWidth * 4);

This looks kind of like what you need. I'm assuming bmpBits in here is either a byte array or a memory stream either of which could then be saved off or at least give you something to look at to see if you're actually getting pixel data



来源:https://stackoverflow.com/questions/44908867/reading-datastream-sharpdx-error-all-values-are-0

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!