2017-09-01 67 views
-2

我正在开发一个解码jpeg文件并使用canvas.drawBitmap()在画布上绘制位图的android应用程序。我正在使用BitmapFactory.decodeStream()将jpeg解码为位图。解码大位图时出现OutOfMemoryError

当我使用诸如2560x1536等分辨率的图像时,一切正常。最近,我做了一个压力测试,试图打开一个非常大的分辨率为5400x3600的jpeg。我的应用程序崩溃,错误为“java.lang.OutOfMemoryError”。

这里是堆栈跟踪:

java.lang.OutOfMemoryError 
    at android.graphics.BitmapFactory.nativeDecodeStream(Native Method) 
    at android.graphics.BitmapFactory.decodeStreamInternal(BitmapFactory.java:720) 
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:696) 
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:734) 
    ... 

这是可以理解的,因为这是一个大的图像和解码的位图使用了大量的内存。

但是,我想了解的是在同一部手机上,如果使用图库应用程序,图库应用程序可以显示相同的大图像而不会有任何问题。

在同一部手机上,如果我还尝试用一些图片编辑工具打开相同的大图片,我认为它也应该将jpeg解码为位图,然后一切正常。这些应用需要多一点的时间才能显示图像,但图像会在屏幕上加载和绘制。

我想了解我可能做错了什么,与其他应用程序相比有什么不同?

+1

你的答案就在这里[链接] {} https://stackoverflow.com/questions/25719620/how-to-solve-java-lang-outofmemoryerror-trouble-in-android –

+0

是否将这些图像存储在可绘制的文件夹中? – Shruti

+0

欢迎@RichardT –

回答

0

首先,您需要设置

android:largeHeap="true" 

在Android清单。 然后这是幻想,相同大小的图像显示在系统库中。实际上,每个图书馆或图库通过保持图像的高宽比和质量来根据屏幕上的可用尺寸调整图像的大小。

所以你需要调整你的图像的大小,然后才能得到大的图像形成系统。

载入大的位图高效

读取的位图尺寸和类型,

的BitmapFactory类提供了用于创建来自不同源的位图数解码方法(decodeByteArray()decodeFile()decodeResource()等)。根据您的图像数据源选择最合适的解码方法。这些方法试图为构造的位图分配内存,因此很容易导致OutOfMemory异常。每种类型的解码方法都有额外的签名,可让您通过BitmapFactory.Options类指定解码选项。在解码时将inJustDecodeBounds属性设置为true可避免内存分配,对于位图对象返回null,但设置outWidth,outHeightoutMimeType。该技术允许您在构建位图之前读取图像数据的尺寸和类型(以及内存分配)。

BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
BitmapFactory.decodeResource(getResources(), R.id.myimage, options); 
int imageHeight = options.outHeight; 
int imageWidth = options.outWidth; 
String imageType = options.outMimeType; 

为了避免java.lang.OutOfMemory例外,对其进行解码,除非你绝对信任来源为您提供了可用内存内舒适适合预见的大小的图像数据之前检查的位图的尺寸。

将缩小后的版本加载到内存中 既然图像尺寸是已知的,它们可以用来决定是应该将完整图像加载到内存中还是应该加载二次采样版本。以下是一些需要考虑的因素:

在内存中加载完整映像的预计内存使用量。 根据应用程序的其他内存要求,您愿意承诺加载此映像的内存量。 图像要加载到的目标ImageView或UI组件的尺寸。 当前设备的屏幕大小和密度。

See Link

0

OutOfMemoryError

当Java虚拟机无法分配一个对象,因为 它是内存不足,并没有更多的内存时可以由 垃圾收集器提供。

确认,新增

<application 
    android:largeHeap="true" 
    > 

为了避免java.lang.OutOfMemory例外,解码之前,检查一个位图的尺寸,除非你绝对信任来源为您提供可预测大小的图像数据舒服适合可用内存。

阅读Loading Large Bitmaps Efficiently

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, 
     int reqWidth, int reqHeight) { 

    // First decode with inJustDecodeBounds=true to check dimensions 
    final BitmapFactory.Options options = new BitmapFactory.Options(); 
    options.inJustDecodeBounds = true; 
    BitmapFactory.decodeResource(res, resId, options); 

    // Calculate inSampleSize 
    options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); 

    // Decode bitmap with inSampleSize set 
    options.inJustDecodeBounds = false; 
    return BitmapFactory.decodeResource(res, resId, options); 
} 

该方法可以很容易地任意大尺寸的位图加载到一个显示100x100的像素缩略图的ImageView的,如图中下面的代码:

imgOBJ.setImageBitmap(
    decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100)); 

可以检查Solve java.lang.OutOfMemoryError trouble in Android

相关问题