如何裁剪捕获的屏幕截图?

时间:2019-12-12 20:50:48

标签: c# xamarin.forms

捕获屏幕快照非常容易,但是裁剪是另外一个故事,或者至少看起来是这样。我们正在尝试使用SkiaSharp(Xamarin不支持System.Drawing)在Xamarin中模拟解决方案here

当前,我们能够捕获屏幕截图并返回图像,但是如果我们裁剪图像,返回的图像全为黑色。

我们如何正确裁剪捕获的屏幕截图?

注意*:“裁剪图像”部分下的image = image.Subset(rec);是我们试图裁剪的方式。

iOS屏幕截图

public byte[] Capture()
{
    var capture = UIScreen.MainScreen.Capture();
    using (NSData data = capture.AsPNG())
    {
        var bytes = new byte[data.Length];
        Marshal.Copy(data.Bytes, bytes, 0, Convert.ToInt32(data.Length));
        return bytes;
    }
}

Droid屏幕截图

public byte[] Capture()
{
    var rootView = context.Window.DecorView.RootView;

    using (var screenshot = Bitmap.CreateBitmap(
                            rootView.Width,
                            rootView.Height,
                            Bitmap.Config.Argb8888))
    {
        var canvas = new Canvas(screenshot);
        rootView.Draw(canvas);

        using (var stream = new MemoryStream())
        {
            screenshot.Compress(Bitmap.CompressFormat.Png, 90, stream);
            return stream.ToArray();
        }
    }
}

尝试裁剪捕获的屏幕截图

// Use this function to crop a screen shot to a specific element.  
public byte[] test(byte[] screenshotData, View element)
{
    //  locate IntPtr to byte[] of uncropped screenshot
    GCHandle gch = GCHandle.Alloc(screenshotData, GCHandleType.Pinned);
    IntPtr addr = gch.AddrOfPinnedObject();

    //  assign initial bounds
    SKImageInfo info = new SKImageInfo((int)App.Current.MainPage.Width,
        (int)App.Current.MainPage.Height);

    //  create initial pixel map
    using SKPixmap pixmap = new SKPixmap(info, addr);
    //  Release
    gch.Free();

    //  create bitmap
    using SKBitmap bitmap = new SKBitmap();
    //  assign pixel data
    bitmap.InstallPixels(pixmap);

    //  create surface
    using SKSurface surface = SKSurface.Create(info);
    //  create a canvas for drawing
    using SKCanvas canvas = surface.Canvas;
    //  draw
    canvas.DrawBitmap(bitmap, info.Rect);

    //  get an image subset to save
    SKImage image = surface.Snapshot();
    SKRectI rec = new SKRectI((int)element.Bounds.Left, (int)element.Bounds.Top,
        (int)element.Bounds.Right, (int)element.Bounds.Bottom);

    //  crop image
    image = image.Subset(rec);

    byte[] bytes = SKBitmap.FromImage(image).Bytes;
    image.Dispose();
    return bytes;
}

编辑:其他解决方案尝试(无效)

// Use this function to crop a screen shot to a specific element.  
public byte[] test(byte[] screenshotData, View element)
{
    //  locate IntPtr to byte[] of uncropped screenshot
    GCHandle gch = GCHandle.Alloc(screenshotData, GCHandleType.Pinned);
    IntPtr addr = gch.AddrOfPinnedObject();
    //  assign initial bounds
    SKImageInfo info = new SKImageInfo((int)App.Current.MainPage.Width,
        (int)App.Current.MainPage.Height);

    //  create bitmap
    SKBitmap bitmap = new SKBitmap();
    bitmap.InstallPixels(info, addr);

    //  boundaries
    SKRect cropRect = new SKRect((int)element.Bounds.Left, (int)element.Bounds.Top,
        (int)element.Bounds.Right, (int)element.Bounds.Bottom);
    SKBitmap croppedBitmap = new SKBitmap((int)cropRect.Width,
        (int)cropRect.Height);
    SKRect dest = new SKRect(0, 0, cropRect.Width, cropRect.Height);
    SKRect source = new SKRect(cropRect.Left, cropRect.Top,
                               cropRect.Right, cropRect.Bottom);

    //  draw with destination and source rectangles 
    //      to extract a subset of the original bitmap
    using SKCanvas canvas = new SKCanvas(croppedBitmap);
    canvas.DrawBitmap(bitmap, source, dest);
    return croppedBitmap.Bytes;
    //return bitmap.Bytes;
}

1 个答案:

答案 0 :(得分:0)

iOS解决方案

// crop the image, without resizing
private UIImage CropImage(UIImage sourceImage, int crop_x, int crop_y, int width, int height)
{
    var imgSize = sourceImage.Size;
    UIGraphics.BeginImageContextWithOptions(new System.Drawing.SizeF(width, height), false, 0.0f);
    var context = UIGraphics.GetCurrentContext();
    var clippedRect = new RectangleF(0, 0, width, height);
    context.ClipToRect(clippedRect);
    var drawRect = new RectangleF(-crop_x, -crop_y, imgSize.Width, imgSize.Height);
    sourceImage.Draw(drawRect);
    var modifiedImage = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();
    return modifiedImage;
}

here所示。