SkiaSharp 是一个强大的跨平台 2D 图形库,提供了丰富的图像处理能力。本文将深入探讨 SkiaSharp 中图像的加载、保存和基本操作。
C#SkiaSharp SkiaSharp.Views.WindowsForms
C#using System.Drawing;
using System.Windows.Forms;
using SkiaSharp;
using SkiaSharp.Views.Desktop;
namespace AppLoadSave
{
public partial class Form1 : Form
{
private SKBitmap loadedBitmap;
public Form1()
{
InitializeComponent();
}
// 从文件加载图像的方法
private SKBitmap LoadImageFromFile(string filePath)
{
try
{
// 使用 SKBitmap.Decode 方法加载图像
using (var stream = System.IO.File.OpenRead(filePath))
{
return SKBitmap.Decode(stream);
}
}
catch (Exception ex)
{
MessageBox.Show($"图像加载错误: {ex.Message}", "错误"
, MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
}
private Bitmap SKBitmapToSystemBitmap(SKBitmap skBitmap)
{
// 创建一个新的 Bitmap,使用 SKBitmap 的宽度和高度
Bitmap bitmap = new Bitmap(skBitmap.Width, skBitmap.Height,
System.Drawing.Imaging.PixelFormat.Format32bppPArgb);
// 锁定位图的位图数据
System.Drawing.Imaging.BitmapData bmpData = bitmap.LockBits(
new Rectangle(0, 0, bitmap.Width, bitmap.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
bitmap.PixelFormat);
// 复制像素数据
IntPtr ptr = bmpData.Scan0;
int bytes = Math.Abs(bmpData.Stride) * bitmap.Height;
byte[] rgbValues = new byte[bytes];
// 从 SKBitmap 获取像素数据
byte[] skPixels = skBitmap.Bytes;
// 转换颜色通道(BGRA to ARGB)
for (int i = 0; i < skPixels.Length; i += 4)
{
rgbValues[i] = skPixels[i + 2]; // B
rgbValues[i + 1] = skPixels[i + 1]; // G
rgbValues[i + 2] = skPixels[i]; // R
rgbValues[i + 3] = skPixels[i + 3]; // A
}
// 将像素数据复制到位图
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bitmap.UnlockBits(bmpData);
return bitmap;
}
private void btnLoad_Click(object sender, EventArgs e)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "图像文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif";
openFileDialog.Title = "选择图像文件";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
// 加载图像
loadedBitmap = LoadImageFromFile(openFileDialog.FileName);
if (loadedBitmap != null)
{
// 直接从 SKBitmap 创建 Bitmap
Bitmap bitmap = SKBitmapToSystemBitmap(loadedBitmap);
pic.Image = bitmap;
}
}
}
}
}
}

C#SKBitmap LoadImageFromMemory(byte[] imageData)
{
try
{
// 从字节数组创建内存流
using (var stream = new MemoryStream(imageData))
{
return SKBitmap.Decode(stream);
}
}
catch (Exception ex)
{
Console.WriteLine($"内存流图像加载错误: {ex.Message}");
return null;
}
}
C#private void btnSave_Click(object sender, EventArgs e)
{
// 检查 PictureBox 中是否有图像
if (pic.Image == null)
{
MessageBox.Show("没有可保存的图像", "提示",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
using (SaveFileDialog saveFileDialog = new SaveFileDialog())
{
// 设置文件过滤器和标题
saveFileDialog.Filter = "JPEG 图像|*.jpg|PNG 图像|*.png|BMP 图像|*.bmp|GIF 图像|*.gif";
saveFileDialog.Title = "保存图像文件";
// 设置默认文件扩展名
saveFileDialog.DefaultExt = "jpg";
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
// 从 PictureBox 获取图像
Bitmap bitmapToSave = (Bitmap)pic.Image;
// 将 System.Drawing.Bitmap 转换为 SKBitmap
SKBitmap skBitmapToSave = SystemBitmapToSKBitmap(bitmapToSave);
// 根据选择的文件类型确定编码格式
SKEncodedImageFormat imageFormat;
switch (Path.GetExtension(saveFileDialog.FileName).ToLower())
{
case ".png":
imageFormat = SKEncodedImageFormat.Png;
break;
case ".bmp":
imageFormat = SKEncodedImageFormat.Bmp;
break;
case ".gif":
imageFormat = SKEncodedImageFormat.Gif;
break;
default:
imageFormat = SKEncodedImageFormat.Jpeg;
break;
}
// 保存图像
using (var stream = File.OpenWrite(saveFileDialog.FileName))
{
// 压缩质量,对于 JPEG 可以调整(0-100)
int quality = imageFormat == SKEncodedImageFormat.Jpeg ? 90 : 100;
skBitmapToSave.Encode(imageFormat, quality)
.SaveTo(stream);
}
MessageBox.Show("图像保存成功", "成功",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"保存图像时出错: {ex.Message}", "错误",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}
// 新增方法:将 System.Drawing.Bitmap 转换为 SKBitmap
private SKBitmap SystemBitmapToSKBitmap(Bitmap systemBitmap)
{
// 使用 SkiaSharp 直接从 Bitmap 创建 SKBitmap
using (var skImage = SKImage.FromEncodedData(BitmapToBytes(systemBitmap)))
{
return SKBitmap.FromImage(skImage);
}
}
// 辅助方法:将 Bitmap 转换为字节数组
private byte[] BitmapToBytes(Bitmap bitmap)
{
using (var stream = new MemoryStream())
{
// 将 Bitmap 保存到内存流
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Png);
return stream.ToArray();
}
}
using 语句管理 SKBitmap、SKImage 等资源Dispose() 不再使用的对象SkiaSharp 提供了强大且灵活的图像处理能力。通过合理使用其 API,您可以轻松实现复杂的图像加载、保存和转换操作。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!