Xamarin iOS中如何将图片转换为HEIC/HEIF并压缩?
在Xamarin.Forms中实现HEIC/HEIF图片转换与压缩
由于HEIC/HEIF的支持具有平台依赖性,Xamarin.Forms本身没有跨平台原生API,需要通过依赖服务调用各平台原生能力来实现格式转换与压缩,同时替代原Plugin.Media的图片获取逻辑避免自动转JPG。
实现步骤
1. 定义跨平台依赖接口(共享项目)
先统一跨平台调用的接口:
public interface IImageHeicConverter { // 输入源图片路径,输出HEIC格式图片路径,quality为压缩质量(0-100) Task<string> ConvertToHeicAsync(string sourceImagePath, int quality); }
2. iOS平台实现(iOS项目)
iOS从iOS 11开始原生支持HEIC,使用CGImageDestination实现格式转换:
[assembly: Dependency(typeof(ImageHeicConverter_iOS))] namespace YourAppNamespace.iOS { public class ImageHeicConverter_iOS : IImageHeicConverter { public async Task<string> ConvertToHeicAsync(string sourceImagePath, int quality) { var sourceImage = UIImage.FromFile(sourceImagePath); if (sourceImage == null) throw new FileNotFoundException("源图片不存在"); // 创建临时HEIC文件路径 var tempHeicPath = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}.heic"); // 使用ImageIO框架写入HEIC格式并设置压缩质量 using (var imageDestination = CGImageDestination.Create(tempHeicPath, "public.heic", 1, null)) { var qualityProp = new NSDictionary( CGImageDestinationProperties.Quality, (nfloat)(quality / 100.0f) ); imageDestination.AddImage(sourceImage.CGImage, qualityProp); imageDestination.Close(); } return tempHeicPath; } } }
注:iOS 14+可直接使用sourceImage.AsHEIC((nfloat)(quality/100.0f))简化实现,以上写法兼容iOS 11+
3. Android平台实现(Android项目)
Android从API 28(Android 9.0)开始支持HEIF,使用ImageWriter实现格式转换:
[assembly: Dependency(typeof(ImageHeicConverter_Android))] namespace YourAppNamespace.Droid { public class ImageHeicConverter_Android : IImageHeicConverter { public async Task<string> ConvertToHeicAsync(string sourceImagePath, int quality) { if (Build.VERSION.SdkInt < BuildVersionCodes.P) throw new NotSupportedException("仅Android 9.0及以上版本支持HEIF格式"); var sourceBitmap = BitmapFactory.DecodeFile(sourceImagePath); if (sourceBitmap == null) throw new FileNotFoundException("源图片不存在"); // 创建临时HEIC文件 var tempFile = new Java.IO.File(Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryPictures), $"{Guid.NewGuid()}.heic"); var tempHeicPath = tempFile.AbsolutePath; // 写入HEIF格式并设置压缩质量 using var outputStream = new FileOutputStream(tempFile); using var imageWriter = ImageWriter.NewInstance(outputStream, ImageFormat.Heic, 1, null); var inputImage = imageWriter.GetInputImage(); var buffer = inputImage.GetPlanes()[0].Buffer; sourceBitmap.CopyPixelsToBuffer(buffer); var encoderBundle = new Bundle(); encoderBundle.PutInt(ImageEncoder.Quality, quality); imageWriter.SetEncoderProperties(encoderBundle); imageWriter.WriteImage(); sourceBitmap.Recycle(); return tempHeicPath; } } }
4. 图片获取与转换流程
使用Xamarin.Essentials.MediaPicker替代Plugin.Media,直接获取原始图片路径后转换:
// 从相册选择图片 var pickResult = await MediaPicker.PickPhotoAsync(new MediaPickerOptions { Title = "选择图片" }); if (pickResult != null) { // 转换为HEIC并压缩(质量设为70) var heicPath = await DependencyService.Get<IImageHeicConverter>().ConvertToHeicAsync(pickResult.FullPath, 70); // 上传heicPath对应的文件到服务器 } // 拍照获取图片 var captureResult = await MediaPicker.CapturePhotoAsync(); if (captureResult != null) { var heicPath = await DependencyService.Get<IImageHeicConverter>().ConvertToHeicAsync(captureResult.FullPath, 60); // 上传逻辑 }
5. 关键注意事项
- 权限配置:iOS需在
Info.plist添加NSCameraUsageDescription、NSPhotoLibraryUsageDescription;Android需在AndroidManifest.xml添加CAMERA、READ_EXTERNAL_STORAGE(Android 10+需ACCESS_MEDIA_LOCATION)权限。 - 兼容性兜底:对不支持HEIC的Android低版本设备,可添加JPG格式的 fallback 转换逻辑。
- 双重压缩:若需更小文件,可先按比例缩小图片分辨率,再进行HEIC格式压缩。
内容的提问来源于stack exchange,提问作者ramdev
相关产品推荐
相关产品推荐

