使用 SkiaSharp 旋转照片
Rotate photo with SkiaSharp
我正在尝试使用以下代码将 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.
我做错了什么?
你可能想做这样的事情:
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;
}
}
造成这种情况(或您的未按预期工作)的原因是您在旋转位图本身。您基本上拍摄了一张图像,然后将其复制到第一张图像上。因此,您仍然有下图的边距。
我所做的是创建一个新的位图,然后在上面绘制解码后的位图。
第二个 "issue" 是您正在旋转图像,但没有改变 canvas 尺寸。如果位图为 50x100,然后旋转 90 度,则位图现在为 100x50。由于位图一旦创建就无法实际更改其尺寸,因此您必须创建一个新位图。您可以在输出图像中看到这一点,因为它实际上被裁剪了一点。
希望对您有所帮助。
Matthew 的解决方案也适用于我,但当我尝试将位图旋转超过 90° 或 -90°(绘制位图 "out of display")时遇到问题。我强烈推荐使用这个 solution。稍微修改的结果:
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.Translate(rotatedWidth / 2, rotatedHeight / 2);
surface.RotateDegrees((float)angle);
surface.Translate(-originalWidth / 2, -originalHeight / 2);
surface.DrawBitmap(bitmap, new SKPoint());
}
return rotatedBitmap;
}
在我的例子中,当我需要在 Xamarin.iOS 平台上旋转图片时,我使用了这个(曾经尝试过的人都知道),效果很好。
我正在尝试使用以下代码将 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.
我做错了什么?
你可能想做这样的事情:
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;
}
}
造成这种情况(或您的未按预期工作)的原因是您在旋转位图本身。您基本上拍摄了一张图像,然后将其复制到第一张图像上。因此,您仍然有下图的边距。
我所做的是创建一个新的位图,然后在上面绘制解码后的位图。
第二个 "issue" 是您正在旋转图像,但没有改变 canvas 尺寸。如果位图为 50x100,然后旋转 90 度,则位图现在为 100x50。由于位图一旦创建就无法实际更改其尺寸,因此您必须创建一个新位图。您可以在输出图像中看到这一点,因为它实际上被裁剪了一点。
希望对您有所帮助。
Matthew 的解决方案也适用于我,但当我尝试将位图旋转超过 90° 或 -90°(绘制位图 "out of display")时遇到问题。我强烈推荐使用这个 solution。稍微修改的结果:
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.Translate(rotatedWidth / 2, rotatedHeight / 2);
surface.RotateDegrees((float)angle);
surface.Translate(-originalWidth / 2, -originalHeight / 2);
surface.DrawBitmap(bitmap, new SKPoint());
}
return rotatedBitmap;
}
在我的例子中,当我需要在 Xamarin.iOS 平台上旋转图片时,我使用了这个(曾经尝试过的人都知道),效果很好。