如何在Xamarin.Android中保存、获取并使用合并生成的Bitmap?
嘿,你已经搞定了Bitmap合并的第一步,先把你没写完的合并代码补全(应该是用Canvas把第二张图绘制到第一张上吧?):
string OnePath = "backgroundimage"; string TwoPath = "objectimage"; var OneImage = BitmapFactory.DecodeResource(Resources, Resources.GetIdentifier(OnePath, "drawable", PackageName)); var TwoImage = BitmapFactory.DecodeResource(Resources, Resources.GetIdentifier(TwoPath, "mipmap", PackageName)); // 复制背景图并开启可编辑模式 Bitmap bitmap = OneImage.Copy(Bitmap.Config.Argb8888, true); // 创建Canvas来绘制第二张图 Canvas canvas = new Canvas(bitmap); // 把第二张图绘制到背景图的左上角,你可以调整坐标或大小,比如用Rect来缩放 canvas.DrawBitmap(TwoImage, 0, 0, null); // 记得用完的Bitmap要回收,避免内存泄漏 OneImage.Recycle(); TwoImage.Recycle();
接下来咱们一步步实现存储、保存、查看和使用这些功能:
一、保存Bitmap到本地
根据你的需求,分两种存储场景:
1. 保存到应用内部存储(仅本应用可访问,无需额外权限)
这种方式适合不需要用户在系统相册看到的图片:
private void SaveBitmapToInternalStorage(Bitmap bitmap, string fileName) { try { // 打开应用内部的输出流 using (var stream = OpenFileOutput(fileName, FileCreationMode.Private)) { // 压缩Bitmap为PNG格式(也可以用JPEG,第二个参数是质量0-100) bitmap.Compress(Bitmap.CompressFormat.Png, 100, stream); } Toast.MakeText(this, "保存成功到内部存储", ToastLength.Short).Show(); } catch (Exception ex) { Toast.MakeText(this, $"保存失败:{ex.Message}", ToastLength.Short).Show(); } }
调用示例:SaveBitmapToInternalStorage(bitmap, "merged_image.png");
2. 保存到外部存储(系统相册可查看,需处理权限)
Android 10及以上推荐用MediaStore来保存,避免权限问题:
private async Task SaveBitmapToGallery(Bitmap bitmap) { try { // 准备图片的元数据 var values = new ContentValues(); values.Put(MediaStore.Images.Media.Columns.DisplayName, "merged_image_" + DateTime.Now.Ticks); values.Put(MediaStore.Images.Media.Columns.MimeType, "image/png"); values.Put(MediaStore.Images.Media.Columns.RelativePath, Environment.DirectoryPictures + "/MyAppImages"); // 获取ContentResolver并插入元数据 var uri = ContentResolver.Insert(MediaStore.Images.Media.ExternalContentUri, values); if (uri == null) throw new Exception("无法获取存储URI"); // 写入Bitmap数据 using (var stream = ContentResolver.OpenOutputStream(uri)) { bitmap.Compress(Bitmap.CompressFormat.Png, 100, stream); } // 通知系统相册更新 MediaScannerConnection.ScanFile(this, new string[] { uri.Path }, null, null); Toast.MakeText(this, "已保存到相册", ToastLength.Short).Show(); } catch (Exception ex) { Toast.MakeText(this, $"保存到相册失败:{ex.Message}", ToastLength.Short).Show(); } }
调用示例:await SaveBitmapToGallery(bitmap);(注意在异步方法中调用)
二、查看已保存的Bitmap
1. 从内部存储读取
private Bitmap LoadBitmapFromInternalStorage(string fileName) { try { using (var stream = OpenFileInput(fileName)) { return BitmapFactory.DecodeStream(stream); } } catch (Exception ex) { Toast.MakeText(this, $"读取失败:{ex.Message}", ToastLength.Short).Show(); return null; } }
2. 从外部存储/相册读取
如果是自己保存的图片,可以通过URI直接读取,这里给个通用的通过URI读取的方法:
private Bitmap LoadBitmapFromUri(Uri uri) { try { using (var stream = ContentResolver.OpenInputStream(uri)) { return BitmapFactory.DecodeStream(stream); } } catch (Exception ex) { Toast.MakeText(this, $"读取失败:{ex.Message}", ToastLength.Short).Show(); return null; } }
三、在应用中使用已保存的Bitmap
最常见的就是显示到ImageView:
// 从内部存储读取并显示 var savedBitmap = LoadBitmapFromInternalStorage("merged_image.png"); if (savedBitmap != null) { imageView.SetImageBitmap(savedBitmap); } // 或者直接用合并后的Bitmap显示 imageView.SetImageBitmap(bitmap);
也可以把Bitmap转换成Drawable作为控件背景:
Drawable drawable = new BitmapDrawable(Resources, bitmap); button.SetBackground(drawable);
注意事项
- 内存管理:Bitmap很占内存,用完记得调用
bitmap.Recycle();,并设置bitmap = null;,尤其是在页面销毁时,避免内存泄漏。 - 权限处理:如果是Android 9及以下保存到外部存储,需要在Manifest中添加
WRITE_EXTERNAL_STORAGE权限,并在运行时申请;Android 10+用MediaStore无需这个权限,但如果要访问其他应用的文件,需要额外权限。 - 压缩优化:保存时可以根据需求选择JPEG格式(压缩率更高),调整压缩质量参数,避免图片过大。
内容的提问来源于stack exchange,提问作者Carlos Rodrigez
相关产品推荐
相关产品推荐

