使用SkiaSharp旋转照片

11

我正在尝试使用SkiaSharp将照片旋转90度,以下是代码:

    public SKBitmap Rotate()
    {
        var bitmap = SKBitmap.Decode("test.jpg");
        using (var surface = new SKCanvas(bitmap))
        {
            surface.RotateDegrees(90, bitmap.Width / 2, bitmap.Height / 2);
            surface.DrawBitmap(bitmap.Copy(), 0, 0);
        }

        return bitmap;
     }

但是当我将位图保存为 JPEG 文件时,图片的顶部和底部都有边距。
原始图片:http://imgur.com/pGAuko8。 旋转后的图片:http://imgur.com/bYxpmI7
我做错了什么?

https://github.com/mono/SkiaSharp/issues/836#issuecomment-489913279 - Nick Kovalsky
2个回答

21
您可能想要做类似这样的事情:
public static SKBitmap Rotate()
{
    using (var bitmap = SKBitmap.Decode("test.jpg"))
    {
        var rotated = new SKBitmap(bitmap.Height, bitmap.Width);

        using (var surface = new SKCanvas(rotated))
        {
            surface.Translate(rotated.Width, 0);
            surface.RotateDegrees(90);
            surface.DrawBitmap(bitmap, 0, 0);
        }

        return rotated;
    }
}
这(或者说你的代码没有按预期工作)的原因是你将位图在其自身上进行了旋转。实际上,你已经拿到一张图片,然后把它复制并绘制到第一张图片上。因此,你仍然有来自下面那张图像的边距。
我的做法是创建一个新的位图,然后将解码后的位图绘制在上面。
第二个“问题”是你旋转了图像,但没有改变画布的尺寸。如果位图是50x100,然后你旋转90度,位图现在就变成了100x50。由于你无法在创建后更改位图的尺寸,因此你必须创建一个新的位图。你可以在输出图像中看到这一点,因为它实际上被裁剪了一点。
希望这能够帮助你。

18

Matthew的解决方案对我也有效,但是当我尝试将位图旋转超过90°或-90°时出现了问题(位图被绘制“超出显示器”)。我强烈推荐使用这个[解决方案] 1。稍作修改后的结果:

public static SKBitmap Rotate(SKBitmap bitmap, double angle)
    {
        double radians = Math.PI * angle / 180;
        float sine = (float)Math.Abs(Math.Sin(radians));
        float cosine = (float)Math.Abs(Math.Cos(radians));
        int originalWidth = bitmap.Width;
        int originalHeight = bitmap.Height;
        int rotatedWidth = (int)(cosine * originalWidth + sine * originalHeight);
        int rotatedHeight = (int)(cosine * originalHeight + sine * originalWidth);

        var rotatedBitmap = new SKBitmap(rotatedWidth, rotatedHeight);

        using (var surface = new SKCanvas(rotatedBitmap))
        {
            surface.Clear();
            surface.Translate(rotatedWidth / 2, rotatedHeight / 2);
            surface.RotateDegrees((float)angle);
            surface.Translate(-originalWidth / 2, -originalHeight / 2);
            surface.DrawBitmap(bitmap, new SKPoint());
        }
        return rotatedBitmap;
    }

在我的情况下,当我需要在Xamarin.iOS平台上旋转图片时(任何尝试过的人都知道),我使用了它,效果非常好。

1
在开始旋转之前,请确保调用 surface.Clear(),否则可能会出现一些图像伪影。 - user2339814
经过3天的黑屏和图像旋转后裁剪的痛苦,这个解决方案帮助我完美地完成了它。非常感谢! - Kranatos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接