如何将Xamarin ImageSource转换为可像素操作的格式(如SkiaSharp/GDI)
Xamarin.Forms图片像素级操作解决方案
一、SkiaSharp:正确将ImageSource转为可读写SKBitmap
你之前的代码问题在于ImageSource没有直接的ToStream()方法,需要根据不同的ImageSource类型异步获取流,再解码为可修改的SKBitmap。以下是通用实现:
using SkiaSharp; using Xamarin.Forms; using System.IO; using System.Threading.Tasks; public static async Task<SKBitmap> ImageSourceToSKBitmapAsync(ImageSource imageSource) { SKBitmap skBitmap = null; Stream stream = null; try { // 根据ImageSource类型获取对应流 if (imageSource is FileImageSource fileSource) { stream = File.OpenRead(fileSource.File); } else if (imageSource is UriImageSource uriSource) { using var httpClient = new System.Net.Http.HttpClient(); stream = await httpClient.GetStreamAsync(uriSource.Uri); } else if (imageSource is StreamImageSource streamSource) { stream = await streamSource.Stream(CancellationToken.None); } if (stream != null) { skBitmap = SKBitmap.Decode(stream); // 确保Bitmap可读写(原解码的Bitmap可能为只读) if (!skBitmap.IsMutable) { skBitmap = skBitmap.Copy(); } } } finally { stream?.Dispose(); } return skBitmap; }
像素读写示例
ImageSource myImageSource = // 你的ImageSource实例 SKBitmap bitmap = await ImageSourceToSKBitmapAsync(myImageSource); if (bitmap != null && bitmap.Width > 0 && bitmap.Height > 0) { // 获取(10,10)位置的像素颜色 SKColor pixelColor = bitmap.GetPixel(10, 10); // 设置(10,10)位置为红色 bitmap.SetPixel(10, 10, SKColors.Red); }
二、GDI+方案(仅Windows平台适用)
GDI+仅支持Windows平台(如Xamarin.Windows),移动端(Android、iOS)无法使用。若你的项目仅针对Windows,可使用System.Drawing.Common库(.NET 6+需在项目文件中启用Windows兼容):
using System.Drawing; using Xamarin.Forms; using System.IO; using System.Threading.Tasks; public static async Task<Bitmap> ImageSourceToBitmapAsync(ImageSource imageSource) { Bitmap bitmap = null; Stream stream = null; try { // 同样先获取流,逻辑与SkiaSharp一致 if (imageSource is FileImageSource fileSource) { stream = File.OpenRead(fileSource.File); } else if (imageSource is UriImageSource uriSource) { using var httpClient = new System.Net.Http.HttpClient(); stream = await httpClient.GetStreamAsync(uriSource.Uri); } else if (imageSource is StreamImageSource streamSource) { stream = await streamSource.Stream(CancellationToken.None); } if (stream != null) { bitmap = new Bitmap(stream); // 创建可读写副本(原Bitmap可能只读) bitmap = new Bitmap(bitmap); } } finally { stream?.Dispose(); } return bitmap; }
像素读写示例
Bitmap gdiBitmap = await ImageSourceToBitmapAsync(myImageSource); if (gdiBitmap != null) { // 获取(10,10)位置像素 Color pixel = gdiBitmap.GetPixel(10, 10); // 设置(10,10)位置为蓝色 gdiBitmap.SetPixel(10, 10, Color.Blue); }
三、其他替代方案
- ImageSharp:跨平台图片处理库,支持.NET Standard,转换逻辑类似,先获取流再解码为
Image对象,同样支持像素级读写。 - 注意事项:所有Bitmap对象使用完毕后需调用
Dispose()释放资源,避免内存泄漏;UI线程操作控件时需切换回主线程。
内容的提问来源于stack exchange,提问作者user23066555
相关产品推荐
相关产品推荐

