C# 如何将ImageCropper输出的3000x2000图片缩放到600分辨率且低画质损失
实现图片缩放的两种方案
你可以直接通过本地路径完成图片缩放,不需要提前拿到流对象,以下两种方案都可以实现低画质损失的缩放,目标分辨率可控制在600左右:
方案1:使用Plugin.ImageResizer插件(最简实现)
这是专门为Xamarin设计的图片处理插件,支持直接传入图片路径完成缩放,不需要手动处理流转换:
- 先通过NuGet安装
Plugin.ImageResizer到你的共享项目和各平台项目 - 在
ImageCropper的Success回调中直接调用插件方法即可,代码示例如下:
new ImageCropper() { PageTitle = "Crop Photo", AspectRatioX = 4, AspectRatioY = 3, CropShape = ImageCropper.CropShapeType.Rectangle, Success = (imagePath) => { Device.BeginInvokeOnMainThread(async () => { // 直接传入原路径,设置最大边为600,压缩质量为90%(值越高画质越好,体积越大) var resizedImagePath = await CrossImageResizer.Current.ResizeImageWithPathAsync( imagePath, 600, // 最大宽度,高度会按4:3比例自动适配为450 90); // 压缩质量,范围0-100,85-95区间画质损失基本可忽略 // 后续使用resizedImagePath即可,生成的缩放后图片默认保存在缓存目录 }); } }
方案2:使用SkiaSharp手动实现(可控性更高)
如果你的项目已经引入了SkiaSharp,不需要额外安装其他插件,可以自己实现缩放逻辑,方便自定义插值算法、压缩参数等,进一步降低画质损失:
using SkiaSharp; using System.IO; using Xamarin.Essentials; public string ResizeImage(string originalPath, int maxSize, int quality = 90) { // 从路径读取原始图片 using var originalBitmap = SKBitmap.Decode(originalPath); // 计算缩放比例,保持4:3比例不变 var scale = (float)maxSize / Math.Max(originalBitmap.Width, originalBitmap.Height); var newWidth = (int)(originalBitmap.Width * scale); var newHeight = (int)(originalBitmap.Height * scale); // 用高质量插值算法缩放 using var resizedBitmap = originalBitmap.Resize(new SKSizeI(newWidth, newHeight), SKFilterQuality.High); // 编码保存图片,设置压缩质量 var resizedPath = Path.Combine(FileSystem.CacheDirectory, $"resized_{Path.GetFileName(originalPath)}"); using var fs = File.OpenWrite(resizedPath); resizedBitmap.Encode(SKEncodedImageFormat.Jpeg, quality).SaveTo(fs); return resizedPath; }
在回调中直接调用上面的方法即可:
Success = (imagePath) => { Device.BeginInvokeOnMainThread(() => { var resizedPath = ResizeImage(imagePath, 600, 90); // 后续使用resizedPath }); }
低画质损失的优化要点
- 压缩质量设置在85-95区间即可,JPEG格式在这个区间的画质损失肉眼几乎不可察,体积可压缩到原大小的1/5-1/10
- 缩放时选择高质量插值算法,避免出现锯齿、模糊问题
- 优先保持原始宽高比,避免拉伸变形带来的观感损失
内容的提问来源于stack exchange,提问作者user4659118
相关产品推荐
相关产品推荐

