Xamarin.Forms加载SMB大图片遇Drawing too large bitmap错误求解决方案
解决Xamarin.Forms加载SMB大图片时的"Drawing too large bitmap"错误
你的问题根源在于图片的像素尺寸超过了Android系统允许的最大位图大小,而不是文件体积——你之前判断stream1.Length的方式只限制了文件大小,对像素尺寸无效。要解决这个问题,需要在将图片流转为ImageSource之前,先压缩图片的分辨率。
推荐使用跨平台图形库SkiaSharp来处理图片压缩,无需编写平台特定代码,步骤如下:
1. 添加SkiaSharp依赖
在你的Xamarin.Forms项目中安装NuGet包:SkiaSharp.Views.Forms
2. 编写图片压缩方法
添加一个用于调整图片流分辨率的工具方法:
private Stream ResizeImageStream(Stream inputStream, int maxWidth, int maxHeight) { using var originalBitmap = SKBitmap.Decode(inputStream); int originalWidth = originalBitmap.Width; int originalHeight = originalBitmap.Height; // 计算缩放比例,保持图片宽高比 float scaleFactor = Math.Min((float)maxWidth / originalWidth, (float)maxHeight / originalHeight); // 如果原图尺寸小于等于目标尺寸,直接返回原流 if (scaleFactor >= 1) { inputStream.Position = 0; return inputStream; } int newWidth = (int)(originalWidth * scaleFactor); int newHeight = (int)(originalHeight * scaleFactor); // 生成压缩后的位图 using var resizedBitmap = originalBitmap.Resize(new SKImageInfo(newWidth, newHeight), SKFilterQuality.High); using var image = SKImage.FromBitmap(resizedBitmap); // 编码为JPEG,质量80(可根据需求调整,范围0-100) using var data = image.Encode(SKEncodedImageFormat.Jpeg, 80); var outputStream = new MemoryStream(); data.SaveTo(outputStream); outputStream.Position = 0; return outputStream; }
3. 修改原有加载图片的代码
替换你原有的图片加载逻辑,加入压缩处理:
if (!String.IsNullOrEmpty(CurrentProduct.Image)) { SharpCifs.Config.SetProperty("jcifs.smb.client.lport", "8080"); var auth = new NtlmPasswordAuthentication("CLD", "login", "password"); string path = $@"smb://file/products/{CurrentProduct.Image}".Replace("\\", "/"); var file = new SmbFile(path, auth); try { if (file.Exists()) { // 使用using自动释放流,避免内存泄漏 using var readStream = file.GetInputStream(); using var memStream = new MemoryStream(); readStream.CopyTo(memStream); memStream.Position = 0; // 压缩图片到最大1080x1920(可根据你的UI需求调整尺寸) using var resizedStream = ResizeImageStream(memStream, 1080, 1920); // 生成ImageSource时,需要重新复制流(因为Stream只能读取一次) ProductImage = ImageSource.FromStream(() => { var stream = new MemoryStream(); resizedStream.Position = 0; resizedStream.CopyTo(stream); stream.Position = 0; return stream; }); InfoColSpan = 1; } } catch (Exception ex) { Common.AlertError(ex, "Impossible de charger l'image"); } }
关键说明
- 宽高比保持:压缩时通过计算最小缩放比例,确保图片不会被拉伸变形
- 尺寸调整:你可以根据应用的UI显示需求,修改
ResizeImageStream方法中的maxWidth和maxHeight参数(比如设置为设备屏幕的分辨率) - 内存优化:使用
using语句自动释放流和位图资源,避免内存泄漏 - 替代方案:如果不想使用SkiaSharp,也可以通过Xamarin.Forms的依赖服务调用平台原生API(比如Android的
BitmapFactory.Options设置inSampleSize),但跨平台实现复杂度更高
内容的提问来源于stack exchange,提问作者Elgate
相关产品推荐
相关产品推荐

