SkiaSharp 提供了强大的图像处理能力,其中图像旋转是最常用的操作之一。本文将深入探讨SkiaSharp中图像旋转的多种方法和技巧。
C#SkiaSharp SkiaSharp.Views.WindowsForms
C#using System.Windows.Forms;
using SkiaSharp;
namespace AppRotation
{
public partial class Form1 : Form
{
private SKBitmap originalBitmap;
private string currentImagePath;
public Form1()
{
InitializeComponent();
}
private void btnLoad_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "Image Files|*.png;*.jpg;*.jpeg;*.bmp;*.gif";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
currentImagePath = openFileDialog.FileName;
using (var fileStream = new FileStream(currentImagePath, FileMode.Open))
{
originalBitmap = SKBitmap.Decode(fileStream);
UpdateRotatedImage(pic, tbAngle.Value);
btnSave.Enabled = true;
}
}
}
}
private void tbAngle_Scroll(object sender, EventArgs e)
{
lblAngle.Text = $"Rotation Angle: {tbAngle.Value}°";
if (originalBitmap != null)
{
UpdateRotatedImage(pic, tbAngle.Value);
}
}
private void btnSave_Click(object sender, EventArgs e)
{
if (originalBitmap == null) return;
using (SaveFileDialog saveFileDialog = new SaveFileDialog())
{
saveFileDialog.Filter = "PNG Image|*.png|JPEG Image|*.jpg|BMP Image|*.bmp";
saveFileDialog.DefaultExt = "png";
saveFileDialog.AddExtension = true;
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
using (SKBitmap rotatedBitmap = RotateImage(originalBitmap, tbAngle.Value))
{
using (SKImage image = SKImage.FromBitmap(rotatedBitmap))
using (SKData data = image.Encode(SKEncodedImageFormat.Png, 100))
using (FileStream stream = new FileStream(saveFileDialog.FileName, FileMode.Create))
{
data.SaveTo(stream);
}
}
MessageBox.Show("Image saved successfully!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
private void UpdateRotatedImage(PictureBox pic, int angle)
{
if (originalBitmap == null) return;
using (SKBitmap rotatedBitmap = RotateImage(originalBitmap, angle))
{
using (SKImage image = SKImage.FromBitmap(rotatedBitmap))
using (SKData data = image.Encode())
using (MemoryStream memStream = new MemoryStream())
{
data.SaveTo(memStream);
memStream.Position = 0;
if (pic.Image != null)
{
pic.Image.Dispose();
}
pic.Image = new Bitmap(memStream);
}
}
}
public SKBitmap RotateImage(SKBitmap originalBitmap, float angle)
{
// 创建一个新的位图,大小适应旋转后的图像
SKBitmap rotatedBitmap = new SKBitmap(
(int)(Math.Abs(originalBitmap.Width * Math.Cos(angle * Math.PI / 180)) +
Math.Abs(originalBitmap.Height * Math.Sin(angle * Math.PI / 180))),
(int)(Math.Abs(originalBitmap.Width * Math.Sin(angle * Math.PI / 180)) +
Math.Abs(originalBitmap.Height * Math.Cos(angle * Math.PI / 180)))
);
using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
{
// Clear canvas with transparent background
canvas.Clear(SKColors.Transparent);
// 将画布中心移动到图像中心
canvas.Translate(rotatedBitmap.Width / 2f, rotatedBitmap.Height / 2f);
// 旋转画布
canvas.RotateDegrees(angle);
// 绘制原始图像,使其居中
canvas.DrawBitmap(originalBitmap,
new SKPoint(-originalBitmap.Width / 2f, -originalBitmap.Height / 2f));
}
return rotatedBitmap;
}
}
}

C#public SKBitmap RotateImageInPlace(SKBitmap originalBitmap, float angle)
{
SKBitmap rotatedBitmap = new SKBitmap(originalBitmap.Width, originalBitmap.Height);
using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
{
// 填充背景(可选)
canvas.Clear(SKColors.Transparent);
// 将画布中心移动到图像中心
canvas.Translate(originalBitmap.Width / 2f, originalBitmap.Height / 2f);
// 旋转画布
canvas.RotateDegrees(angle);
// 绘制原始图像,使其居中
canvas.DrawBitmap(originalBitmap,
new SKPoint(-originalBitmap.Width / 2f, -originalBitmap.Height / 2f));
}
return rotatedBitmap;
}

C#public SKBitmap SmoothRotateImage(SKBitmap originalBitmap, float angle)
{
// 创建一个新的位图,考虑旋转后的最大尺寸
SKBitmap rotatedBitmap = new SKBitmap(
(int)(Math.Abs(originalBitmap.Width * Math.Cos(angle * Math.PI / 180)) +
Math.Abs(originalBitmap.Height * Math.Sin(angle * Math.PI / 180))),
(int)(Math.Abs(originalBitmap.Width * Math.Sin(angle * Math.PI / 180)) +
Math.Abs(originalBitmap.Height * Math.Cos(angle * Math.PI / 180)))
);
using (SKCanvas canvas = new SKCanvas(rotatedBitmap))
{
// 使用高质量的插值模式
canvas.SetMatrix(SKMatrix.CreateRotationDegrees(angle,
rotatedBitmap.Width / 2f,
rotatedBitmap.Height / 2f));
// 使用双线性插值绘制图像
canvas.DrawBitmap(originalBitmap,
new SKRect(0, 0, originalBitmap.Width, originalBitmap.Height),
new SKRect(0, 0, rotatedBitmap.Width, rotatedBitmap.Height),
new SKPaint
{
FilterQuality = SKFilterQuality.High
});
}
return rotatedBitmap;
}

## 注意事项
- 旋转会改变图像的尺寸和质量
- 大角度旋转可能导致图像边缘出现锯齿
- 选择合适的插值模式可以提高旋转质量
## 性能建议
- 对于频繁旋转,考虑重用 `SKCanvas` 和 `SKBitmap`
- 使用 `SKFilterQuality` 平衡图像质量和性能
- 对于大图像,考虑异步处理
## 结语
SkiaSharp 提供了灵活且强大的图像旋转功能。通过合理使用旋转方法,可以轻松实现各种图像处理需求。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!