问题描述
我正在开发一个使用大图像(1390 × 870:150kb - 50kb)的应用.我在点击触发器/ImageView 时添加图像.
I'm working on an app that uses large images (1390 × 870 : 150kb - 50kb). I'm adding images as I tap a trigger/ImageView.
在某个时候,我遇到内存不足错误:
At a certain point I'm getting an out of memory error:
java.lang.OutOfMemoryError
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:613)
E/AndroidRuntime(23369): at android.graphics.BitmapFactory.decodeFile(BitmapFactory.java:378)
要调整图像大小,我这样做:
To resize the image I'm doing this:
Bitmap productIndex = null;
final String imageLoc = IMAGE_LOCATION;
InputStream imageStream;
try {
imageStream = new FileInputStream(imageLoc);
productIndex = decodeSampledBitmapFromResource(getResources(), imageLoc, 400, 400);
productIV.setImageBitmap(productIndex);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
public static Bitmap decodeSampledBitmapFromResource(Resources res, String resId, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(resId, options);
}
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 / 3;
final int halfWidth = width / 3;
// 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;
}
我通过这种调整大小的方式来节省 Android Docs 的空间:高效加载大位图
I got this way of resizing to save space from the Android Docs:Loading Large Bitmaps Efficiently
根据日志,这就是decodeSampledBitmapFromResource
方法的罪魁祸首:
According to the log this like is the culprit in the decodeSampledBitmapFromResource
method :
return BitmapFactory.decodeFile(resId, options);
----- 编辑 -----这是我将每个项目添加到 FrameLayout 的方式.
----- edit -----Here is how I'm adding each item to the FrameLayout.
for(int ps=0;ps<productSplit.size();ps++){
//split each product by the equals sign
List<String> productItem = Arrays.asList(productSplit.get(ps).split("="));
String tempCarID = productItem.get(0);
tempCarID = tempCarID.replace(" ", "");
if(String.valueOf(carID).equals(tempCarID)){
ImageView productIV = new ImageView(Configurator.this);
LayoutParams productParams = new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
productIV.setId(Integer.parseInt(partIdsList.get(x)));
productIV.setLayoutParams(productParams);
final String imageLoc = productItem.get(2);
InputStream imageStream;
try {
imageStream = new FileInputStream(imageLoc);
productIndex = decodeSampledBitmapFromResource(getResources(), imageLoc, 400, 400);
productIV.setImageBitmap(productIndex);
} catch (FileNotFoundException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
productLayers.addView(productIV);
}
}
推荐答案
您可以使用另一个位图配置来大幅减小图像的大小.默认为 RGB-config ARGB8888,这意味着使用四个 8 位通道(红色、绿色、蓝色、alhpa).Alpha 是位图的透明度.这会占用大量内存 - imagesize X 4.因此,如果 imagesize 为 4 兆像素,则 16 兆字节将立即分配到堆上 - 很快就会耗尽内存.
You can use another bitmap-config to heavily decrease the size of the images. The default is RGB-config ARGB8888 which means four 8-bit channels are used (red, green, blue, alhpa). Alpha is transparency of the bitmap. This occupy a lot of memory - imagesize X 4. So if the imagesize is 4 megapixel 16 megabytes will immidiately be allocated on the heap - quickly exhausting the memory.
相反 - 使用 RGB_565 这在某种程度上会降低质量 - 但为了弥补这一点,您可以抖动图像.
Instead - use RGB_565 which to some extent deteriorate the quality - but to compensate this you can dither the images.
因此 - 在您的方法 decodeSampledBitmapFromResource 中添加以下代码段:
So - to your method decodeSampledBitmapFromResource - add the following snippets:
options.inPreferredConfig = Config.RGB_565;
options.inDither = true;
在您的代码中:
public static Bitmap decodeSampledBitmapFromResource(Resources res, String resId, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
options.inPreferredConfig = Config.RGB_565;
options.inDither = true;
return BitmapFactory.decodeFile(resId, options);
}
参考文献:
http://developer.android.com/reference/android/graphics/Bitmap.Config.html#ARGB_8888
这篇关于如何在Android中加载大图像并避免内存不足错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!