android BitmapFactory的OutOfMemoryError: bitmap ...
2014-05-22 17:15
274 查看
原文地址:/article/3555123.html网上有很多解决android加载bitmap内存溢出的方法,搜了一圈做下整理总结。项目里需求是拍摄多图之后上传,部分手机会内存溢出。常用一种解决方法:即将载入的图片缩小,这种方式以牺牲图片的质量为代价。在BitmapFactory中有一个内部类BitmapFactory.Options,其中当options.inSampleSize值>1时,根据文档:Ifsettoavalue>1,requeststhedecodertosubsampletheoriginalimage,returningasmallerimagetosavememory.(1->decodesfullsize;2->decodes1/4thsize;4->decode1/16thsize).Becauseyourarelyneedtoshow
andhavefullsizebitmapimagesonyourphone.Formanipulationssmallersizesareusuallyenough.options.inSampleSize是以2的指数的倒数被进行放缩现在问题是怎么确定inSampleSize的值?每张图片的放缩大小的比例应该是不一样的!这样的话就要运行时动态确定。在BitmapFactory.Options中提供了另一个成员inJustDecodeBounds。设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。Android提供了一种动态计算的方法,见computeSampleSize().
以上只做为参考,我们只要用这函数即可,
替换
原因:查看BitmapFactory的源码,对比一下两者的实现,可以发现decodeFile()最终是以流的方式生成bitmapdecodeFile源码:
decodeFileDescriptor的源码,可以找到native本地方法decodeFileDescriptor,通过底层生成bitmapdecodeFileDescriptor源码:
2、当在android设备中载入较大图片资源时,可以创建一些临时空间,将载入的资源载入到临时空间中。
?完整代码:
andhavefullsizebitmapimagesonyourphone.Formanipulationssmallersizesareusuallyenough.options.inSampleSize是以2的指数的倒数被进行放缩现在问题是怎么确定inSampleSize的值?每张图片的放缩大小的比例应该是不一样的!这样的话就要运行时动态确定。在BitmapFactory.Options中提供了另一个成员inJustDecodeBounds。设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。Android提供了一种动态计算的方法,见computeSampleSize().
01 | public static int computeSampleSize(BitmapFactory.Optionsoptions, |
02 | int minSideLength, int maxNumOfPixels){ |
03 | int initialSize=computeInitialSampleSize(options,minSideLength, |
04 | maxNumOfPixels); |
05 |
06 | int roundedSize; |
07 | if (initialSize<= 8 ){ |
08 | roundedSize= 1 ; |
09 | while (roundedSize<initialSize){ |
10 | roundedSize<<= 1 ; |
11 | } |
12 | } else { |
13 | roundedSize=(initialSize+ 7 )/ 8 * 8 ; |
14 | } |
15 |
16 | return roundedSize; |
17 | } |
18 |
19 | private static int
|
20 | int minSideLength, int maxNumOfPixels){ |
21 | double w=options.outWidth; |
22 | double h=options.outHeight; |
23 |
24 | int lowerBound=(maxNumOfPixels==- 1 )? 1 : |
25 | ( int )Math.ceil(Math.sqrt(w*h/maxNumOfPixels)); |
26 | int upperBound=(minSideLength==- 1 )? 128 : |
27 | ( int )Math.min(Math.floor(w/minSideLength), |
28 | Math.floor(h/minSideLength)); |
29 |
30 | if (upperBound<lowerBound){ |
31 | return lowerBound; |
32 | } |
33 |
34 | if ((maxNumOfPixels==- 1 )&& |
35 | (minSideLength==- 1 )){ |
36 | return 1 ; |
37 | } else if
1 ){ |
38 | return lowerBound; |
39 | } else { |
40 | return upperBound; |
41 | } |
42 | } |
opts.inSampleSize=computeSampleSize(opts,-
1
,
128
*
128
);要点:1、用decodeFileDescriptor()来生成bimap比decodeFile()省内存
1 | FileInputStreamis== new FileInputStream(path); |
2 | bmp=BitmapFactory.decodeFileDescriptor(is.getFD(), null ,opts); |
1 | Bitmapbmp=BitmapFactory.decodeFile(imageFile,opts); |
2 | imageView.setImageBitmap(bmp); |
01 | public static BitmapdecodeFile(StringpathName,Optionsopts){ |
02 | Bitmapbm= null ; |
03 | InputStreamstream= null ; |
04 | try { |
05 | stream= new FileInputStream(pathName); |
06 | bm=decodeStream(stream, null ,opts); |
07 | } catch (Exceptione){ |
08 | /*donothing. |
09 | Iftheexceptionhappenedonopen,bmwillbenull. |
10 | */ |
11 | } finally { |
12 | if (stream!= null ){ |
13 | try { |
14 | stream.close(); |
15 | } catch (IOExceptione){ |
16 | //donothinghere |
17 | } |
18 | } |
19 | } |
20 | return bm; |
21 | } |
01 | public static BitmapdecodeFileDescriptor(FileDescriptorfd,RectoutPadding,Optionsopts){ |
02 | if (nativeIsSeekable(fd)){ |
03 | Bitmapbm=nativeDecodeFileDescriptor(fd,outPadding,opts); |
04 | if (bm== null
null &&opts.inBitmap!= null ){ |
05 | throw new IllegalArgumentException( "Problemdecodingintoexistingbitmap" ); |
06 | } |
07 | return finishDecode(bm,outPadding,opts); |
08 | } else { |
09 | FileInputStreamfis= new FileInputStream(fd); |
10 | try { |
11 | return decodeStream(fis,outPadding,opts); |
12 | } finally { |
13 | try { |
14 | fis.close(); |
15 | } catch (Throwablet){ /*ignore*/ } |
16 | } |
17 | } |
18 | } |
19 |
20 | private static native
|
1 | opts.inTempStorage= new byte [ 16 * 1024 ]; |
01 | public static OutputStreamdecodeBitmap(Stringpath){ |
02 |
03 | BitmapFactory.Optionsopts= new BitmapFactory.Options(); |
04 | opts.inJustDecodeBounds= true ; //设置成了true,不占用内存,只获取bitmap宽高 |
05 | BitmapFactory.decodeFile(path,opts); |
06 | opts.inSampleSize=computeSampleSize(opts,- 1 , 1024 * 800 ); |
07 |
08 | opts.inJustDecodeBounds= false ; //这里一定要将其设置回false,因为之前我们将其设置成了true |
09 | opts.inPurgeable= true ; |
10 | opts.inInputShareable= true ; |
11 | opts.inDither= false ; |
12 | opts.inPurgeable= true ; |
13 | opts.inTempStorage= new byte [ 16 * 1024 ]; |
14 | FileInputStreamis= null ; |
15 | Bitmapbmp= null ; |
16 | InputStreamins= null ; |
17 | ByteArrayOutputStreambaos= null ; |
18 | try { |
19 | is= new FileInputStream(path); |
20 | bmp=BitmapFactory.decodeFileDescriptor(is.getFD(), null ,opts); double scale=getScaling(opts.outWidth*opts.outHeight, 1024 * 600 ); |
21 | Bitmapbmp2=Bitmap.createScaledBitmap(bmp, |
22 | ( int )(opts.outWidth*scale), |
23 | ( int )(opts.outHeight*scale), true ); |
24 | bmp.recycle(); |
25 | baos= new ByteArrayOutputStream(); |
26 | bmp2.compress(Bitmap.CompressFormat.JPEG, 100 ,baos); |
27 | bmp2.recycle(); |
28 | return baos; |
29 | } catch (FileNotFoundExceptione){ |
30 | e.printStackTrace(); |
31 | } catch (IOExceptione){ |
32 | e.printStackTrace(); |
33 | } finally { |
34 | try { |
35 | is.close(); |
36 | ins.close(); |
37 | baos.close(); |
38 | } catch (IOExceptione){ |
39 | e.printStackTrace(); |
40 | } |
41 | System.gc(); |
42 | } |
43 | return baos; |
44 | } |
45 |
46 | private static double getScaling( int src, int des){ |
47 | /** |
48 | *目标尺寸÷原尺寸sqrt开方,得出宽高百分比 |
49 | */ |
50 | double scale=Math.sqrt(( double )des/( double )src); |
51 | return scale; |
52 | } |
相关文章推荐
- Android BitmapFactory.decodeStream方法OutOfMemoryError 解决方法
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- Android BitmapFactory的OutOfMemoryError问题,最近看到
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决..
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android BitmapFactory的OutOfMemoryError 解决
- android BitmapFactory的OutOfMemoryError: bitmap ...
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- Android:BitmapFactory decoding大文件中产生OutOfMemoryError解决规划
- android BitmapFactory的OutOfMemoryError: bitmap size exceeds VM budget解决方案
- android-java.lang.OutOfMemoryError: bitmap size exceeds VM budge
- BitmapFactory decoding大文件中产生OutOfMemoryError解决方案
- android:java.lang.OutOfMemoryError: bitmap size exceeds VM budget---缩略图