【问题标题】:Xamarin Forms UWP Capture Screenshot Include Signature PadXamarin Forms UWP 捕获屏幕截图包括签名板
【发布时间】:2018-04-23 21:45:51
【问题描述】:

我有一个使用签名板 (https://github.com/xamarin/SignaturePad) 的 Xamarin 表单页面。我正在尝试捕获整个视图的屏幕截图。它也应该包括签名。

但是,使用以下代码,我注意到签名没有显示出来。

捕获包括签名在内的整个页面的最佳方式是什么? (不仅仅是签名)

public class ScreenshotService : IScreenshotService
{
    public async Task<byte[]> CaptureAsync()
    {
    var rtb = new RenderTargetBitmap();
    await rtb.RenderAsync(Window.Current.Content);

    var pixelBuffer = await rtb.GetPixelsAsync();
    var pixels = pixelBuffer.ToArray();

    // Useful for rendering in the correct DPI
    var displayInformation = DisplayInformation.GetForCurrentView();

    var stream = new InMemoryRandomAccessStream();
    var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
    encoder.SetPixelData(BitmapPixelFormat.Bgra8,
    BitmapAlphaMode.Premultiplied,
    (uint)rtb.PixelWidth,
    (uint)rtb.PixelHeight,
    displayInformation.RawDpiX,
    displayInformation.RawDpiY,
    pixels);

    await encoder.FlushAsync();
    stream.Seek(0);

    var readStram = stream.AsStreamForRead();
    var bytes = new byte[readStram.Length];
    readStram.Read(bytes, 0, bytes.Length);

    return bytes;
}
}

【问题讨论】:

    标签: xamarin xamarin.forms uwp signaturepad


    【解决方案1】:

    根据RenderTargetBitmap类的“XAML视觉效果和RenderTargetBitmap捕获能力”:

    无法捕获的内容在捕获的图像中将显示为空白,但同一视觉树中的其他内容仍然可以捕获并呈现(无法捕获的内容的存在不会使该 XAML 组合的完整捕获)。

    因此可能是 InkCanvas 的内容不可捕获。但是,您可以使用Win2D。更多内容可以参考以下代码。

    public async Task<Stream> CaptureAsync(Stream Tem)
    {
        var rtb = new RenderTargetBitmap();
        await rtb.RenderAsync(Window.Current.Content);
    
        var pixelBuffer = await rtb.GetPixelsAsync();
        var pixels = pixelBuffer.ToArray();
    
        var displayInformation = DisplayInformation.GetForCurrentView();
        var stream = new InMemoryRandomAccessStream();
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
        encoder.SetPixelData(BitmapPixelFormat.Bgra8,
        BitmapAlphaMode.Premultiplied,
        (uint)rtb.PixelWidth,
        (uint)rtb.PixelHeight,
        displayInformation.RawDpiX,
        displayInformation.RawDpiY,
        pixels);
        await encoder.FlushAsync();
        stream.Seek(0);
        var readStram = stream.AsStreamForRead();
    
        var pagebitmap = await GetSoftwareBitmap(readStram);
        var softwareBitmap = await GetSoftwareBitmap(Tem);
    
        CanvasDevice device = CanvasDevice.GetSharedDevice();
        CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, rtb.PixelWidth, rtb.PixelHeight, 96);
    
        using (var ds = renderTarget.CreateDrawingSession())
        {
            ds.Clear(Colors.White);
            var page = CanvasBitmap.CreateFromSoftwareBitmap(device, pagebitmap);
            var image = CanvasBitmap.CreateFromSoftwareBitmap(device, softwareBitmap);
            ds.DrawImage(page);
            ds.DrawImage(image);
        }
    
        InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
        await renderTarget.SaveAsync(randomAccessStream, CanvasBitmapFileFormat.Jpeg, 1f);
        return randomAccessStream.AsStream();
    }
    
     private async Task<SoftwareBitmap> GetSoftwareBitmap(Stream data)
     {
       BitmapDecoder pagedecoder = await BitmapDecoder.CreateAsync(data.AsRandomAccessStream());
       return await pagedecoder.GetSoftwareBitmapAsync(BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
     }
    

    IScreenshotServicecs 接口

    public interface IScreenshotServicecs
    {
        Task<Stream> CaptureAsync(Stream stream);
    }
    

    用法

    var stream = await SignatureView.GetImageStreamAsync(SignaturePad.Forms.SignatureImageFormat.Png);
    var data = await DependencyService.Get<IScreenshotServicecs>().CaptureAsync(stream);
    MyImage.Source = ImageSource.FromStream(() => data);
    

    【讨论】:

    • 感谢您的回答。打算看看这个。我对这种方法的问题是 iOS/Android 不需要传入 Stream。他们可以简单地处理捕获整个视图,包括签名
    • 如何获取转换后的图像并作为图像字节数组返回?我不想在本地存储,只是将字节数组流传递给 API。我试过了:return renderTarget.GetPixelBytes();
    • 是的,当然可以,我把图片保存在本地方便我们测试。
    • 谢谢!你有一个例子吗?尝试返回 GetPixelBytes() 并没有给我正确渲染的图像。
    • 是的,我已经上传了代码sample
    【解决方案2】:

    这是我的最终实现,包括转换为字节数组。

        public async Task<byte[]> CaptureAsync(Stream signatureStream)
        {
            var rtb = new RenderTargetBitmap();
            await rtb.RenderAsync(Window.Current.Content);
    
            var pixelBuffer = await rtb.GetPixelsAsync();
            var pixels = pixelBuffer.ToArray();
    
            var displayInformation = DisplayInformation.GetForCurrentView();
            var stream = new InMemoryRandomAccessStream();
            var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream);
            encoder.SetPixelData(BitmapPixelFormat.Bgra8,
            BitmapAlphaMode.Premultiplied,
            (uint)rtb.PixelWidth,
            (uint)rtb.PixelHeight,
            displayInformation.RawDpiX,
            displayInformation.RawDpiY,
            pixels);
            await encoder.FlushAsync();
            stream.Seek(0);
            var readStram = stream.AsStreamForRead();
    
            var pagebitmap = await GetSoftwareBitmap(readStram);
            var softwareBitmap = await GetSoftwareBitmap(signatureStream);
    
            CanvasDevice device = CanvasDevice.GetSharedDevice();
            CanvasRenderTarget renderTarget = new CanvasRenderTarget(device, rtb.PixelWidth, rtb.PixelHeight, 96);
    
            using (var ds = renderTarget.CreateDrawingSession())
            {
                ds.Clear(Colors.White);
                var page = CanvasBitmap.CreateFromSoftwareBitmap(device, pagebitmap);
                var image = CanvasBitmap.CreateFromSoftwareBitmap(device, softwareBitmap);
                ds.DrawImage(page);
                ds.DrawImage(image, 50, 55);
            }
    
            InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
            await renderTarget.SaveAsync(randomAccessStream, CanvasBitmapFileFormat.Jpeg, 1f);
    
            var fileBytes = new byte[randomAccessStream.Size];
            using (var reader = new DataReader(randomAccessStream))
            {
                await reader.LoadAsync((uint)randomAccessStream.Size);
                reader.ReadBytes(fileBytes);
            }
    
            return fileBytes;
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-13
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 2020-04-20
      相关资源
      最近更新 更多