SkiaSharp 提供了多种强大的图像缩放方法,可以满足不同场景下的图像处理需求。本文将详细探讨 SkiaSharp 中图像缩放的各种技术和最佳实践。
Nuget 安装包
SkiaSharp
SkiaSharp.Views.WindowsForms
基本缩放方法
等比例缩放
using System.Windows.Forms;
using SkiaSharp;
namespace AppImageScaling
{
public partial class Form1 : Form
{
private SKBitmap originalImage;
public Form1()
{
InitializeComponent();
}
private void btnLoad_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "Image Files|*.bmp;*.jpg;*.jpeg;*.png;*.gif";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
originalImage = SKBitmap.Decode(openFileDialog.FileName);
SKBitmap scaledImage = ScaleImageProportionally(originalImage, 400);
pic.Image = BitmapFromSKBitmap(scaledImage);
}
}
}
public SKBitmap ScaleImageProportionally(SKBitmap originalImage, int targetWidth)
{
// 计算等比例缩放的高度
float aspectRatio = (float)originalImage.Height / originalImage.Width;
int targetHeight = (int)(targetWidth * aspectRatio);
// 创建缩放后的位图
SKBitmap scaledBitmap = new SKBitmap(targetWidth, targetHeight);
// 使用高质量缩放
using (SKCanvas canvas = new SKCanvas(scaledBitmap))
{
canvas.SetMatrix(SKMatrix.CreateScale(
(float)targetWidth / originalImage.Width,
(float)targetHeight / originalImage.Height
));
// 绘制原始图像
canvas.DrawBitmap(originalImage, 0, 0);
}
return scaledBitmap;
}
private Bitmap BitmapFromSKBitmap(SKBitmap skBitmap)
{
using (var image = SKImage.FromBitmap(skBitmap))
using (var data = image.Encode(SKEncodedImageFormat.Png, 100))
using (var stream = new System.IO.MemoryStream(data.ToArray()))
{
returnnew Bitmap(stream);
}
}
}
}

指定缩放质量
SkiaSharp 提供多种缩放滤波器,可以根据不同需求选择:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using SkiaSharp;
namespace AppImageScaling
{
public partial class Form2 : Form
{
private SKBitmap originalImage;
public Form2()
{
InitializeComponent();
}
private void btnLoad_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "Image Files|*.bmp;*.jpg;*.jpeg;*.png;*.gif";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
originalImage = SKBitmap.Decode(openFileDialog.FileName);
int targetWidth = 400;
int targetHeight = (int)((float)originalImage.Height / originalImage.Width * targetWidth);
SKFilterQuality filterQuality = GetFilterQuality(cboQuality.SelectedItem.ToString());
SKBitmap scaledImage = ScaleImageWithFilter(originalImage, targetWidth, targetHeight, filterQuality);
pic.Image = BitmapFromSKBitmap(scaledImage);
}
}
}
public SKBitmap ScaleImageWithFilter(SKBitmap originalImage, int targetWidth
, int targetHeight, SKFilterQuality filterQuality)
{
// 创建目标位图
SKBitmap scaledBitmap = new SKBitmap(targetWidth, targetHeight);
using (SKCanvas canvas = new SKCanvas(scaledBitmap))
{
// 创建绘制对象并设置过滤质量
using (var paint = new SKPaint())
{
paint.FilterQuality = filterQuality;
// 通过指定目标点和目标尺寸来绘制原始图像到目标位图
canvas.DrawBitmap(originalImage, new SKRect(0, 0, targetWidth, targetHeight),
new SKRect(0, 0, originalImage.Width, originalImage.Height), paint);
}
}
return scaledBitmap;
}
private SKFilterQuality GetFilterQuality(string quality)
{
return quality switch
{
"Low" => SKFilterQuality.Low,
"Medium" => SKFilterQuality.Medium,
"High" => SKFilterQuality.High,
_ => SKFilterQuality.None,
};
}
private Bitmap BitmapFromSKBitmap(SKBitmap skBitmap)
{
using (var image = SKImage.FromBitmap(skBitmap))
using (var data = image.Encode(SKEncodedImageFormat.Png, 100))
using (var stream = new System.IO.MemoryStream(data.ToArray()))
{
returnnew Bitmap(stream);
}
}
}
}

高级缩放技术
保持图像清晰度的缩放
public SKBitmap ScaleImageWithSharpness(SKBitmap originalImage, float scaleFactor)
{
// 计算目标尺寸
int targetWidth = (int)(originalImage.Width * scaleFactor);
int targetHeight = (int)(originalImage.Height * scaleFactor);
// 创建高清缩放位图
SKBitmap scaledBitmap = new SKBitmap(targetWidth, targetHeight);
using (SKCanvas canvas = new SKCanvas(scaledBitmap))
{
// 使用高质量插值
canvas.DrawBitmap(originalImage,
new SKRect(0, 0, originalImage.Width, originalImage.Height),
new SKRect(0, 0, targetWidth, targetHeight),
new SKPaint
{
FilterQuality = SKFilterQuality.High
}
);
}
return scaledBitmap;
}
缩放实践建议
性能与质量平衡
- 对于缩略图,使用
SKFilterQuality.Low
- 对于高质量展示,使用
SKFilterQuality.High
- 大幅缩放时,考虑分步缩放以保持图像质量
异常处理
public SKBitmap SafeScaleImage(SKBitmap originalImage, int targetWidth, int targetHeight)
{
// 检查输入有效性
if (originalImage == null)
thrownew ArgumentNullException(nameof(originalImage));
if (targetWidth <= 0 || targetHeight <= 0)
thrownew ArgumentException("目标尺寸必须为正数");
try
{
return ScaleImageWithFilter(
originalImage,
targetWidth,
targetHeight,
SKFilterQuality.Medium
);
}
catch (Exception ex)
{
// 记录错误或返回原图
Console.WriteLine($"图像缩放失败:{ex.Message}");
return originalImage;
}
}
总结
SkiaSharp 提供了灵活且强大的图像缩放功能,能够通过选择合适的缩放方法和质量滤波器,在性能与图像质量之间实现良好平衡。在使用过程中,需要注意几个关键技巧:保持图像的纵横比以避免变形,根据需求选择适当的缩放质量以优化视觉效果,妥善处理边界情况以确保输出的准确性,同时权衡性能开销以满足实际应用的需求。这些策略有助于高效地实现高质量的图像缩放。
阅读原文:原文链接
该文章在 2025/9/4 14:39:27 编辑过