设置图片inSampleSize但是内存没变?或许你应该看看这个
2017-11-13 17:27
281 查看
对于安卓开发来说,内存溢出(oom)是安卓程序员不可绕过的坎,特别是对于大图片来说,加载时候的大内存更是常常让人胆战心惊。
很多安卓程序员都知道,避免图片加载大内存的最常用方法,那就是用BitmapFactory的options,设置这个options的inSampleSize来达到将图片按照实际显示大小去缩小自己图片,来达到减少内存。
若是你去百度inSampleSize,那么你会看到最多的用法是这样的:
看起来好像完全没有问题,根据自己想要的的图片大小,然后去计算将原图缩放的inSampleSize,然后赋值给bitmap以达到缩放图片大小。
很多人看到这样算法便喜不自胜急忙将它复制到自己工程,可是复制进去之后他们却傻眼了,内存跟以前没用时候差不多啊。
为什么会这样?
因为,inSampleSize只能为整数啊。
我们举个例子,假如有一张高度为700的图片,你想把它缩放为500,你要是用上面那个算法去算,你会发现,你算出来的inSampleSize其实为1!!!
而1,那就是图片不变,没有压缩
在这里说一下,inSampleSize的值只能为2的倍数,1,4,8,16……
1的话是不变,2的话是图片变为原来4分之一大小,8是变为原来64分之一大小,以此类推
所以到了最后,你会发现你想要压缩的图片其实根本没有被压缩。
好吧,就算有变,但其实也很难,甚至几乎不可能变到你想要的图片大小,就比如上面说的那个例子,无论你设置inSampleSize为什么值,你都会发现,你最终得到的图片要么太大要么太小。
但是安卓怎么可能那么垃圾,
对的,安卓才不会这么垃圾呢,
其实与inSampleSize相关的还有几个参数,比如inScaled,inTargetDensity,inDensity。
这些参数其实非常有用,与inSampleSize一起用才会完美。
其中:
inScaled:将它设置为true,那么代表这张图片可以缩放
inDensity:图片的原来密度,默认一般为160.
inTargetDensity:图片的目标密度,图片操作之后的密度
其实你设置一张图片的BitmapFactory的options,这张图片的输出宽高是这样决定的:
所以你要是现将一张700的图片缩小为600,你可以计算一下图片的inTargetDensity,如下面方法
比如我将一张宽700图片缩小为宽450的图片,在没设置inTargetDensity的时候
![](https://oscdn.geek-share.com/Uploads/Images/Content/201711/766c264dbc6d47bbf1d80397f5509339)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201711/3d53a043379e51410ade63c97054d948)
计算出来的inSampleSize为1,图片尺寸很大,没有变
所占用内存:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201711/76907ca1ca769cf79eee769d2008bcc4)
差不多40M
而在设置了inTargetDensity 之后
![](https://oscdn.geek-share.com/Uploads/Images/Content/201711/12e154ad36e4bb753f52d25c560612e0)
![](https://oscdn.geek-share.com/Uploads/Images/Content/201711/b5ef83e65efbea8c3586190431d52adb)
计算出来的inSampleSize仍然为1,但是图片尺寸却变为我想要获取的大小450了!!!
而所占用的内存:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201711/fc14c01bc659fce3b54b7520e7d40c28)
只有14M左右!!!!!!!!!!
40?14!是不是感觉世界瞬间美好很多啦~
对了,后面顺便说一下,若你将根据这个方法得到的图片赋值给另一个bitmap的时候,可能会出现,这个被赋值的bitmap图片虽然图片大小不变,但是显示变了,那是因为这个inTargetDensity 属性不会自动赋值给新的bitmap,可以这样做
这样新得到的b图片就会跟原来那张一样了
很多安卓程序员都知道,避免图片加载大内存的最常用方法,那就是用BitmapFactory的options,设置这个options的inSampleSize来达到将图片按照实际显示大小去缩小自己图片,来达到减少内存。
若是你去百度inSampleSize,那么你会看到最多的用法是这样的:
private Bitmap getimage(String srcPath) { BitmapFactory.Options newOpts = new BitmapFactory.Options(); //开始读入图片,此时把options.inJustDecodeBounds 设回true了 newOpts.inJustDecodeBounds = true; Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空 newOpts.inJustDecodeBounds = false; int w = newOpts.outWidth; int h = newOpts.outHeight; //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为 float hh = 800f;//这里设置高度为800f float ww = 480f;//这里设置宽度为480f //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可 int be = 1;//be=1表示不缩放 if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放 be = (int) (newOpts.outWidth / ww); } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放 be = (int) (newOpts.outHeight / hh); } if (be <= 0) be = 1; newOpts.inSampleSize = be;//设置缩放比例 //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了 bitmap = BitmapFactory.decodeFile(srcPath, newOpts); return compressImage(bitmap);//压缩好比例大小后再进行质量压缩 }
看起来好像完全没有问题,根据自己想要的的图片大小,然后去计算将原图缩放的inSampleSize,然后赋值给bitmap以达到缩放图片大小。
很多人看到这样算法便喜不自胜急忙将它复制到自己工程,可是复制进去之后他们却傻眼了,内存跟以前没用时候差不多啊。
为什么会这样?
因为,inSampleSize只能为整数啊。
我们举个例子,假如有一张高度为700的图片,你想把它缩放为500,你要是用上面那个算法去算,你会发现,你算出来的inSampleSize其实为1!!!
而1,那就是图片不变,没有压缩
在这里说一下,inSampleSize的值只能为2的倍数,1,4,8,16……
1的话是不变,2的话是图片变为原来4分之一大小,8是变为原来64分之一大小,以此类推
所以到了最后,你会发现你想要压缩的图片其实根本没有被压缩。
好吧,就算有变,但其实也很难,甚至几乎不可能变到你想要的图片大小,就比如上面说的那个例子,无论你设置inSampleSize为什么值,你都会发现,你最终得到的图片要么太大要么太小。
但是安卓怎么可能那么垃圾,
对的,安卓才不会这么垃圾呢,
其实与inSampleSize相关的还有几个参数,比如inScaled,inTargetDensity,inDensity。
这些参数其实非常有用,与inSampleSize一起用才会完美。
其中:
inScaled:将它设置为true,那么代表这张图片可以缩放
inDensity:图片的原来密度,默认一般为160.
inTargetDensity:图片的目标密度,图片操作之后的密度
其实你设置一张图片的BitmapFactory的options,这张图片的输出宽高是这样决定的:
输出图片的宽高= (原图片的宽高 * (inTargetDensity / inDensity)) / inSampleSize
所以你要是现将一张700的图片缩小为600,你可以计算一下图片的inTargetDensity,如下面方法
/** * 获取特定大小缩略图 * @param imageid 图片资源id * @param size 你想要获取的图片大小尺寸 * @return */ public Bitmap getSampleBitmap2(int imageid,int size){ BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds=true; BitmapFactory.decodeResource(getResources(),imageid,options); options.inPreferredConfig = Bitmap.Config.ARGB_8888; options.inSampleSize= calculateInSampleSize(options,size); //设置图片可以缩小 options.inScaled = true; int calsize=options.outHeight>options.outWidth?options.outWidth:options.outHeight; /** * 计算图片缩小的目标密度,在这里说一下,有一条公式: * 输出图片的宽高= (原图片的宽高 * (inTargetDensity / inDensity)) / inSampleSize * 一般来说,图片的options.inDensity默认为160 * 所以inTargetDensity计算公式为:(希望输出的宽高*options.inDensity)/(原来图片的宽高/options.inSampleSize) */ options.inTargetDensity =(size*options.inDensity)/(calsize/options.inSampleSize); options.inJustDecodeBounds = false; Bitmap bitmap = BitmapFactory.decodeResource(getResources(),imageid,options); return bitmap; }
//谷歌源码里面的计算simplesize方法, public int calculateInSampleSize(BitmapFactory.Options options, int size) { int reqWidth,reqHeight; // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; if(options.outHeight>options.outWidth){ reqWidth=size; reqHeight=size*options.outHeight/options.outWidth; }else{ reqWidth=size*options.outWidth/options.outHeight; reqHeight=size; } 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; }
比如我将一张宽700图片缩小为宽450的图片,在没设置inTargetDensity的时候
计算出来的inSampleSize为1,图片尺寸很大,没有变
所占用内存:
差不多40M
而在设置了inTargetDensity 之后
计算出来的inSampleSize仍然为1,但是图片尺寸却变为我想要获取的大小450了!!!
而所占用的内存:
只有14M左右!!!!!!!!!!
40?14!是不是感觉世界瞬间美好很多啦~
对了,后面顺便说一下,若你将根据这个方法得到的图片赋值给另一个bitmap的时候,可能会出现,这个被赋值的bitmap图片虽然图片大小不变,但是显示变了,那是因为这个inTargetDensity 属性不会自动赋值给新的bitmap,可以这样做
//创建一张新的bitmap,跟传入图片一样宽的正方形bitmap, Bitmap b=Bitmap.createBitmap(bitmapSize,bitmapSize, Bitmap.Config.ARGB_8888); //将图片密度修改为上面那张的图片密度 b.setDensity(bitmap.getDensity());
这样新得到的b图片就会跟原来那张一样了
相关文章推荐
- android使用inSampleSize、inScaled、inDensity、inTargetDensity对图片进行缩放
- Android图片缩放,压缩总结(inSampleSize,Matrix比较)
- Android图片缩放,压缩总结(inSampleSize,Matrix比较)
- Android Bitmap内存的管理与优化--降低采样率,inSampleSize的算法
- android使用inSampleSize、inScaled、inDensity、inTargetDensity对图片进行缩放
- 图片缩放 inJustDecodeBounds inSampleSize matrix
- 图片缩放 inJustDecodeBounds inSampleSize
- Android图片尺寸与质量压缩你用对了吗?inSampleSize与quality的浅析
- inSampleSize Matrix 组合缩放图片(bitmap size exceeds 32 bits???)
- 设置SDWebImage中maxCacheSize动态管理图片内存缓存大小无效。maxCacheSize和maxMemoryCost的定义和使用。
- Android图片缩放,压缩总结(inSampleSize,Matrix比较)
- Android图片 BitmapFactory.Options.inSampleSize 采样率不准确问题
- android使用inSampleSize、inScaled、inDensity、inTargetDensity对图片进行缩放
- Java开发者或许应该经常去看看的网站?...
- 设置了全局钩子,但是发现有的程序钩不到,这个问题可能的一个原因
- BitmapFactory.Options.inSampleSize用法
- 让超链接点击后不跳转,可以用href = "#",但是这个#就会锚点到页面最上边 点击链接后不跳转可以设置成
- 把一图片改为画笔,用来画线!!!!!! (有代码)请大家帮忙看看应该怎么改好。
- Android ImageResizer:inSampleSize
- [Android]TextView设置字体大小时应该知道的事-同样的textSize不同的效果