2015-12-22 53 views
1

我基本上是试图压缩,并通过由然而用户在不同的手机使用的OutOfMemoryError问题的应用程序崩溃选定的图像的Base64表示。这里是我的压缩和转换代码:Android的位图压缩不足,导致OutOfMemoryError异常崩溃

Bitmap bm = BitmapFactory.decodeFile(filePath); 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); 
byte[] byteArrayImage = baos.toByteArray(); 
String base64String = Base64.encodeToString(byteArrayImage, Base64.DEFAULT); 

这个过程也是十分缓慢,并导致应用程序有时会崩溃。

这里有一个例外,我得到了:

java.lang.OutOfMemoryError: Failed to allocate a 5035548 byte allocation with 5011320 free bytes and 4MB until OOM 
    at dalvik.system.VMRuntime.newNonMovableArray(Native Method) 
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method) 
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:625) 
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:460) 
    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:973) 
    at android.content.res.Resources.loadDrawableForCookie(Resources.java:2477) 

我应该做什么样的变化?

回答

2
final BitmapFactory.Options options = new BitmapFactory.Options(); 
options.inJustDecodeBounds = true; 
options.inSampleSize = 2; //you can also calculate your inSampleSize 
options.inJustDecodeBounds = false; 
options.inTempStorage = new byte[16 * 1024]; 

Bitmap bm = BitmapFactory.decodeFile(filePath,options); //changed line code 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
bm.compress(Bitmap.CompressFormat.JPEG, 100, baos); 
byte[] byteArrayImage = baos.toByteArray(); 
String base64String = Base64.encodeToString(byteArrayImage, Base64.DEFAULT); 

注:使用android:largeHeap="true"为您的应用程序不被认为是一个理想的解决方案。

下面是来自谷歌的提取物来解释它,

然而,要求一大堆的能力仅用于一 小集合的应用程序,可以证明需要消耗更多的RAM(例如 作为一个大型照片编辑应用程序)。从来没有要求一大堆只是 因为你已经用完了内存,你需要速战速决,你应该 使用它,只有当你确切地知道你所有的内存被分配 以及为什么必须保留。但是,即使您对自己的应用程序有足够的信心,也可以在任何可能的范围内尽可能避免向 发送请求。使用额外的内存将越来越多地损害整体用户体验,因为垃圾收集将花费更长的时间,并且当任务切换或执行其他常见操作时,系统性能可能会更慢。

这里的文档的完整链接https://developer.android.com/training/articles/memory.html

编辑1:对于非常大的图片对于像WhatsApp的图像压缩图像结账的高效灵活,这SO Answer

+0

感谢您的详细解释。使用此解决方案压缩后输出图像的质量如何?它受到很大影响吗? – Dinuka

+0

在平均图像上看起来不错,但图像越高,需要的时间就越长。我们可以加快这一点吗? – Dinuka

+0

是的,你可以为此你必须缩放图像。看看'Edit 1'。 –

0

尝试使用后回收您的位图。并将位图也设置为null。如果你想运行垃圾收集器。

+0

你能告诉我代码吗?我没有做过 – Dinuka

+0

bm.recycle(); BM = NULL;系统。GC(); – ajantha

0

这种方法不会很好地工作,说从照相机拍摄的照片。一张13mp的照片是4128x3096x3字节,大约40兆字节。这就是单独的位图的大小。如果正在对飞创建基-64表示,这将需要另外的40兆和更多一些,则由于基底-64串花费更多个字节来存储比相当的原始字节阵列(位图)。

你真的需要把它变成基础64吗?如果你想上传它,你可以直接通过rest api或多部分发布请求来完成。

,如果你不能这样做,也许你可以每1 MB拆分操作,如,或替代书写字符串到内存中,你可以把它写到文件,并每隔1 MB术后追加呢?

+0

您认为哪种解决方案更好?多部分上传或Base64? Facebook,Instagram等使用哪种方法? – Dinuka

+1

@Earthling'Multipart'是更好的上传图像的解决方案,使用'base64'将图像转换为字符串将其尺寸增加** 33%**,从而带来更多带宽。 –

+0

@VipulAsri你有什么资料可以找?我需要通过休息服务发布上传 – Dinuka