我正在尝试在ImageView
中显示图库中的图像或捕获的相机。我开始在这个过程中获得OOM
。所以我决定找出它是如何工作的。所以我尝试使用不同大小的图像进行观察,
我尝试将19KB图像加载到ImageView
并收到以下错误消息。
无法分配4915212字节分配570452空闲字节和557KB直到OOM
我有2MB图像
无法分配带有16777120个空闲字节的31961100字节分配和29MB直到OOM
2MB
为什么19KB图像需要大约4.6MB的主内存,2MB图像需要30 MB的主内存空间?
PS:我发现很多解决方案,比如根据显示器对图像进行下采样,但没有一个解释过这种行为。
答案 0 :(得分:6)
理想情况下,您将使用ARGB_8888
作为位图。这意味着对于每个像素,分配4个字节(每个字节用于A,R,G,B)。这意味着加载1024x768图像需要1024 * 768 * 4 = 3145728 B = 3072 KB = 3 MB。这就是使用大容量内存的原因。以下信息来自文档:http://developer.android.com/reference/android/graphics/Bitmap.Config.html
Bitmap.Config.ALPHA_8 - 每个像素都存储为单个半透明(alpha)通道。
Bitmap.Config.ARGB_4444 - 此字段在API级别13中已弃用。由于此配置质量较差,建议改用ARGB_8888。
Bitmap.Config.ARGB_8888 - 每个像素存储在4个字节上。
Bitmap.Config.RGB_565 - 每个像素存储在2个字节上,只有RGB通道被编码:红色以5位精度存储(32个可能值),绿色存储6个精度位(64个可能的值)和蓝色以5位精度存储。
答案 1 :(得分:2)
在Android中,图像的每个像素都需要4个字节的内存。因此,如果您从500万像素图像中创建A
,则需要大约20MB。因此,您应该计算所需的样本大小,以便在不加载完整分辨率的情况下显示图像。
即使图像文件只有19KB,Bitmap
对象也会占用更多内存。
尝试创建静态方法来计算所需的样本大小:
Bitmap
然后在加载完整图像之前先检查图像的边界:
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}
有关此内容的更多信息,请参阅开发者指南: https://developer.android.com/training/displaying-bitmaps/load-bitmap.html