Take screenshot to bytes

Hi, I'm trying to take a screenshot and save it as a byte array for posting to the web. I have:

    void TakeScreenshot(TouchEndEventArgs e)
    {
        Image screenshot = new Image();
        Graphics.TakeScreenShot(screenshot);
        byte[] rawData = new byte[] { };
        MemoryBuffer mb = new MemoryBuffer(rawData);
        screenshot.Save(mb);

        try
        {
            Debug.WriteLine(mb.GetData());
        }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.Message);
        }
    }

But every time I try this, it gives me "[0:] Value cannot be null. Parameter name: src" from GetData. I know Graphics.TakeScreenShot is working from printing the width/height before and after. What am I missing here?

On Android and using Urho.Forms if that makes any difference.

Best Answer

  • EgorBoEgorBo BY ✭✭✭
    Accepted Answer

    I've just added SavePNG that returns byte data. Will be available via nuget soon.

Answers

  • EgorBoEgorBo BYXamarin Team ✭✭✭
    edited May 2017

    The problem is - Save(MemoryBuffer) saves it as PNG but there is no any surfaced API to get it's size before saving.
    So as a workaround I can suggest to save the image to a file system and load it to bytes using Image.SavePNG method.
    Also, you can obtain raw pixel data from Image using this code snippet:

       unsafe
        {
            byte[] data = new byte[img.Width * img.Height * img.Depth * img.Components];
            Marshal.Copy((IntPtr)img.Data, data, 0, data.Length);
        }
    
  • EgorBoEgorBo BYXamarin Team ✭✭✭
    Accepted Answer

    I've just added SavePNG that returns byte data. Will be available via nuget soon.

  • DMcLennanDMcLennan GBMember ✭✭

    Thanks for all your work!

  • DMcLennanDMcLennan GBMember ✭✭

    If I use this method through the Urho scene itself (on touch end for example) it works perfectly and I can see from printing out the byte array as base 64 the image is correct. But I'm now facing the issue that if I call my take screenshot method from a xamarin forms button I'll get a blank image (but of the correct dimensions). I'm not sure why this should be the case?

  • KyleColdenKyleColden USMember ✭✭

    I'm seeing the Black image from TakeScreenshot using UWP. It doesn't matter whether I capture it in OnTouchEnd, from my xamarin forms button, whether I invoke to main in my urho app or not. It always comes back as a black image. Tried all the different Save, SavePNG, SaveJPG, etc methods.

    @DMcLennan or anyone else able to get TakeScreenshot working (hopefully on UWP)?

  • dotMortendotMorten USMember ✭✭

    UWP doesn't support taking screenshots of the SwapChainPanel control which is what Urho is using for rendering DirectX content. This is a known (and annoying) limitation on that control.
    It's also documented as a limitation here: docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Media.Imaging.RenderTargetBitmap

  • ClayBrinleeClayBrinlee USMember ✭✭

    I'm using the following in UWP:

    public async Task<byte[]> CaptureScreen()
        {
            //create and capture Window
            var renderTargetBitmap = new RenderTargetBitmap();
            await renderTargetBitmap.RenderAsync(Window.Current.Content);
    
            var pixelpuffer = await renderTargetBitmap.GetPixelsAsync();
            var logicalDpi = DisplayInformation.GetForCurrentView().LogicalDpi;
    
            IRandomAccessStream stream = new InMemoryRandomAccessStream();
            BitmapEncoder encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
            encoder.BitmapTransform.InterpolationMode = BitmapInterpolationMode.Fant;
            encoder.SetPixelData(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Straight, (uint)renderTargetBitmap.PixelWidth, (uint)renderTargetBitmap.PixelHeight, logicalDpi, logicalDpi, pixelpuffer.ToArray());
            await encoder.FlushAsync();
            byte[] resultingBuffer = new byte[stream.Size];
    
            await stream.ReadAsync(resultingBuffer.AsBuffer(), (uint)resultingBuffer.Length, InputStreamOptions.None);
    
            return resultingBuffer;
    
        }
    
Sign In or Register to comment.