Android 加载和裁剪位图时不会出现内存不足异常
我需要从Facebook、Instagram或设备本身裁剪图像。在用户流结束时(他选择了它们),所有的图像都应该发送到服务器。但是它们都是相同的宽高比(例如3/2),因此我需要手动裁剪图像 下面是我的上传服务和裁剪的一个简单示例:Android 加载和裁剪位图时不会出现内存不足异常,android,image,Android,Image,我需要从Facebook、Instagram或设备本身裁剪图像。在用户流结束时(他选择了它们),所有的图像都应该发送到服务器。但是它们都是相同的宽高比(例如3/2),因此我需要手动裁剪图像 下面是我的上传服务和裁剪的一个简单示例: Bitmap bitmap = ImageLoading.getLoader(UploadService.this).loadImageSync(path); //crop calculations Bitmap croppedBitmap = Bitmap.crea
Bitmap bitmap = ImageLoading.getLoader(UploadService.this).loadImageSync(path);
//crop calculations
Bitmap croppedBitmap = Bitmap.createBitmap(bitmap, x, y, w, y);
String croppedPath = saveCroppedImage(croppedBitmap);
然后,我从文件系统中读取这个文件,并将其编码到BASE64以将其发送到后端
当我必须对多个图像执行此操作时,我经常会遇到OOM异常。也许我走错了方向。。在服务器端进行裁剪实际上是我最不想做的事情,因为这样后端就必须查询Facebook或Instagram
加载位图的缩放版本不是一个选项,我不会在设备上显示它
我试过:
- System.gc()
- Bitmap.recycle()李>
- 我真的应该在清单中使用largeHeap吗
注意:我也在为用户流使用Universal Image Loader,这就是为什么我也在上载服务中使用它。我认为您应该在AndroidManifest文件中添加largeHeap=true 其次,如果您使用的是Universal ImageLoader,则可以下载较小尺寸的位图。请查看此代码:
ImageSize targetSize = new ImageSize(80, 50); // result Bitmap will be fit to this size
Bitmap bmp = imageLoader.loadImageSync(imageUri, targetSize, options); // This bitmap will be of specified size.
您可以通过以下链接进一步阅读。我认为您应该在AndroidManifest文件中添加largeHeap=true 其次,如果您使用的是Universal ImageLoader,则可以下载较小尺寸的位图。请查看此代码:
ImageSize targetSize = new ImageSize(80, 50); // result Bitmap will be fit to this size
Bitmap bmp = imageLoader.loadImageSync(imageUri, targetSize, options); // This bitmap will be of specified size.
您可以通过以下链接进一步了解。GC不是您的问题。Android堆变得支离破碎;没有足够大的单个空闲块来满足分配请求。尝试重用
Bitmap
对象(请参见BitmapFactory.Options
上的inBitmap
),这可能需要自己加载图像,而不是使用UIL。理想情况下,您可以找到一种不需要创建图像另一个副本的裁剪方法(就像createBitmap()
可能做的那样)。您还可以在savecropedimage()
中做一些事情来提供帮助。谢谢您的评论!savecropedimage()只使用FileOutputStream并将其压缩为PNG 100。我真的承受不起质量损失。我看过inBitmap,但这似乎限制了不同图像大小的使用。“我看过inBitmap,但这似乎限制了不同图像大小的使用”——API级别19+提供了更大的灵活性,但是是的,它是有限的。另一方面,您可能没有太多的选项,除非您想开始使用NDK并在C/C++中进行图像裁剪。是的,我注意到它在19++上更灵活。我并没有真正了解使用NDK如何改善内存管理?我可能不得不重新考虑整个方法,并最终进行服务器端裁剪。“在这里使用NDK如何改进内存管理?”--很简单:您没有使用Java堆。您可以访问整个免费系统RAM。如果将load crop和save logic移动到NDK中,它会运行得更快,并避免出现OutOfMemoryError
。维护起来更麻烦,尤其是跨CPU体系结构。测试和填充也更繁琐。但是,你可能没有选择。请记住,即使您要求一个大堆
,它也可能不是很大(例如Android One设备)。GC不是您的问题。Android堆变得支离破碎;没有足够大的单个空闲块来满足分配请求。尝试重用Bitmap
对象(请参见BitmapFactory.Options
上的inBitmap
),这可能需要自己加载图像,而不是使用UIL。理想情况下,您可以找到一种不需要创建图像另一个副本的裁剪方法(就像createBitmap()
可能做的那样)。您还可以在savecropedimage()
中做一些事情来提供帮助。谢谢您的评论!savecropedimage()只使用FileOutputStream并将其压缩为PNG 100。我真的承受不起质量损失。我看过inBitmap,但这似乎限制了不同图像大小的使用。“我看过inBitmap,但这似乎限制了不同图像大小的使用”——API级别19+提供了更大的灵活性,但是是的,它是有限的。另一方面,您可能没有太多的选项,除非您想开始使用NDK并在C/C++中进行图像裁剪。是的,我注意到它在19++上更灵活。我并没有真正了解使用NDK如何改善内存管理?我可能不得不重新考虑整个方法,并最终进行服务器端裁剪。“在这里使用NDK如何改进内存管理?”--很简单:您没有使用Java堆。您可以访问整个免费系统RAM。如果将load crop和save logic移动到NDK中,它会运行得更快,并避免出现OutOfMemoryError
。维护起来更麻烦,尤其是跨CPU体系结构。测试和填充也更繁琐。但是,你可能没有选择。请记住,即使您要求一个大堆
,它也可能不是很大(例如,Android One设备)。恐怕这里不允许加载较小版本的位图。我们需要全质量的。我想我可能不得不使用largeHeap,但这听起来像是一个肮脏的代码。我恐怕在这里不能选择加载较小版本的位图。我们需要全质量的。我想我可能不得不使用largeHeap,但它听起来像一个肮脏的代码。