文档章节

BitmapFactory.Options详解

今日竹石
 今日竹石
发布于 2015/04/08 07:06
字数 1512
阅读 409
收藏 2

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

public Bitmap


inBitmap


If set, decode methods that take the Options object will attempt to reuse this bitmap when loading content.


public int


inDensity


The pixel density to use for the bitmap.


public boolean


inDither


If dither is true, the decoder will attempt to dither the decoded image.


public boolean


inInputShareable


This field works in conjuction with inPurgeable.


public boolean


inJustDecodeBounds


If set to true, the decoder will return null (no bitmap), but the out…


public boolean


inMutable


If set, decode methods will always return a mutable Bitmap instead of an immutable one.


public boolean


inPreferQualityOverSpeed


If inPreferQualityOverSpeed is set to true, the decoder will try to decode the reconstructed image to a higher quality even at the expense of the decoding speed.


publicBitmap.Config


inPreferredConfig


If this is non-null, the decoder will try to decode into this internal configuration.


public boolean


inPurgeable


If this is set to true, then the resulting bitmap will allocate its pixels such that they can be purged if the system needs to reclaim memory.


public int


inSampleSize


If set to a value > 1, requests the decoder to subsample the original image, returning a smaller image to save memory.


public boolean


inScaled


When this flag is set, if inDensity and inTargetDensity are not 0, the bitmap will be scaled to match inTargetDensity when loaded, rather than relying on the graphics system scaling it each time it is drawn to a Canvas.


public int


inScreenDensity


The pixel density of the actual screen that is being used.


public int


inTargetDensity


The pixel density of the destination this bitmap will be drawn to.


public byte[]


inTempStorage


Temp storage to use for decoding.


public boolean


mCancel


Flag to indicate that cancel has been called on this object.


public int


outHeight


The resulting height of the bitmap, set independent of the state of inJustDecodeBounds.


public String


outMimeType


If known, this string is set to the mimetype of the decoded image.


public int


outWidth


The resulting width of the bitmap, set independent of the state of inJustDecodeBounds.


 

以上是从android sdk文档里摘出来的,简单看一下说明就明白是什么意思了。

下面我们回到我们的主题上来:怎样获取图片的大小?

思路很简单:

首先我们把这个图片转成Bitmap,然后再利用Bitmap的getWidth()和getHeight()方法就可以取到图片的宽高了。

新问题又来了,在通过BitmapFactory.decodeFile(String path)方法将突破转成Bitmap时,遇到大一些的图片,我们经常会遇到OOM(Out Of Memory)的问题。怎么避免它呢?

这就用到了我们上面提到的BitmapFactory.Options这个类。

BitmapFactory.Options这个类,有一个字段叫做 inJustDecodeBounds 。SDK中对这个成员的说明是这样的:

If set to true, the decoder will return null (no bitmap), but the out…

也就是说,如果我们把它设为true,那么BitmapFactory.decodeFile(String path, Options opt)并不会真的返回一个Bitmap给你,它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM了。

示例代码如下:

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;

Bitmap bmp = BitmapFactory.decodeFile(path, options);

/* 这里返回的bmp是null */

这段代码之后,options.outWidth 和 options.outHeight就是我们想要的宽和高了。

有了宽,高的信息,我们怎样在图片不变形的情况下获取到图片指定大小的缩略图呢?

比如我们需要在图片不变形的前提下得到宽度为200的缩略图。

那么我们需要先计算一下缩放之后,图片的高度是多少 

/* 计算得到图片的高度 */

/* 这里需要主意,如果你需要更高的精度来保证图片不变形的话,需要自己进行一下数学运算 */

int height = options.outHeight * 200 / options.outWidth;

options.outWidth = 200;

options.outHeight = height; 

/* 这样才能真正的返回一个Bitmap给你 */

options.inJustDecodeBounds = false;

Bitmap bmp = BitmapFactory.decodeFile(path, options);

image.setImageBitmap(bmp);

复制代码

这样虽然我们可以得到我们期望大小的ImageView

但是在执行BitmapFactory.decodeFile(path, options);时,并没有节约内存。要想节约内存,还需要用到BitmapFactory.Options这个类里的 inSampleSize 这个成员变量。

我们可以根据图片实际的宽高和我们期望的宽高来计算得到这个值。

inSampleSize = options.outWidth / 200;

另外,为了节约内存我们还可以使用下面的几个字段:

options.inPreferredConfig = Bitmap.Config.ARGB_4444;    // 默认是Bitmap.Config.ARGB_8888

/* 下面两个字段需要组合使用 */

options.inPurgeable = true;

options.inInputShareable = true;




用BitmapFactory解码一张图片时,有时会遇到该错误。这往往是由于图片过大造成的。要想正常使用,则需要分配更少的内存空间来存储。

BitmapFactory.Options.inSampleSize

设置恰当的inSampleSize可以使BitmapFactory分配更少的空间以消除该错误。inSampleSize的具体含义请参考SDK文档。例如:

BitmapFactory.Options opts = new BitmapFactory.Options();

opts.inSampleSize = 4;

Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);

设置恰当的inSampleSize是解决该问题的关键之一。BitmapFactory.Options提供了另一个成员inJustDecodeBounds。

BitmapFactory.Options opts = new BitmapFactory.Options();


opts.inJustDecodeBounds = true;


Bitmap bitmap = BitmapFactory.decodeFile(imageFile, opts);


设置inJustDecodeBounds为true后,decodeFile并不分配空间,但可计算出原始图片的长度和宽度,即opts.width和opts.height。有了这两个参数,再通过一定的算法,即可得到一个恰当的inSampleSize。

查看Android源码,我们得知,为了得到恰当的inSampleSize,Android提供了一种动态计算的方法。

public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {

    int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);

    int roundedSize;

    if (initialSize <= 8) {

        roundedSize = 1;

        while (roundedSize < initialSize) {

            roundedSize <<= 1;

        }

    } else {

        roundedSize = (initialSize + 7) / 8 * 8;

    }

    return roundedSize;

}


private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {

    double w = options.outWidth;

    double h = options.outHeight;

    int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));

    int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));

    if (upperBound < lowerBound) {

        // return the larger one when there is no overlapping zone.

        return lowerBound;

    }

    if ((maxNumOfPixels == -1) && (minSideLength == -1)) {

        return 1;

    } else if (minSideLength == -1) {

        return lowerBound;

    } else {

        return upperBound;

    }


使用该算法,就可动态计算出图片的inSampleSize。


BitmapFactory.Options opts = new BitmapFactory.Options();

opts.inJustDecodeBounds = true;

BitmapFactory.decodeFile(imageFile, opts);

opts.inSampleSize = computeSampleSize(opts, -1, 128*128);  

opts.inJustDecodeBounds = false;

try {

 Bitmap bmp = BitmapFactory.decodeFile(imageFile, opts);

 imageView.setImageBitmap(bmp);

    } catch (OutOfMemoryError err) {

    }





综合上述,完整代码是:


[java] view plaincopy



  1. public static Bitmap createImageThumbnail(String filePath){  

  2.      Bitmap bitmap = null;  

  3.      BitmapFactory.Options opts = new BitmapFactory.Options();  

  4.      opts.inJustDecodeBounds = true;  

  5.      BitmapFactory.decodeFile(filePath, opts);  

  6.   

  7.      opts.inSampleSize = computeSampleSize(opts, -1, 128*128);  

  8.      opts.inJustDecodeBounds = false;  

  9.   

  10.      try {  

  11.          bitmap = BitmapFactory.decodeFile(filePath, opts);  

  12.      }catch (Exception e) {  

  13.         // TODO: handle exception  

  14.     }  

  15.     return bitmap;  

  16. }  

  17.   

  18. public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {  

  19.     int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);  

  20.     int roundedSize;  

  21.     if (initialSize <= 8) {  

  22.         roundedSize = 1;  

  23.         while (roundedSize < initialSize) {  

  24.             roundedSize <<= 1;  

  25.         }  

  26.     } else {  

  27.         roundedSize = (initialSize + 7) / 8 * 8;  

  28.     }  

  29.     return roundedSize;  

  30. }  

  31.   

  32. private static int computeInitialSampleSize(BitmapFactory.Options options,int minSideLength, int maxNumOfPixels) {  

  33.     double w = options.outWidth;  

  34.     double h = options.outHeight;  

  35.     int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));  

  36.     int upperBound = (minSideLength == -1) ? 128 :(int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));  

  37.     if (upperBound < lowerBound) {  

  38.         // return the larger one when there is no overlapping zone.  

  39.         return lowerBound;  

  40.     }  

  41.     if ((maxNumOfPixels == -1) && (minSideLength == -1)) {  

  42.         return 1;  

  43.     } else if (minSideLength == -1) {  

  44.         return lowerBound;  

  45.     } else {  

  46.         return upperBound;  

  47.     }  

  48. }  



© 著作权归作者所有

今日竹石
粉丝 41
博文 227
码字总数 181312
作品 0
朝阳
程序员
私信 提问
BitmapFactory.Options详解

public Bitmap inBitmap If set, decode methods that take the Options object will attempt to reuse this bitmap when loading content. public int inDensity The pixel density to use ......

flying-tomato
2015/07/25
253
0
BitmapFactory.Options详解

这个表格是从android sdk文档里摘出来的,简单看一下说明就明白是什么意思了。 下面我们回到我们的主题上来:怎样获取图片的大小? 思路很简单: 首先我们把这个图片转成Bitmap,然后再利用B...

Thanks
2012/10/24
263
0
Android以最省内存的方式读取本地资源的

方法一: /** * 获取本地图片并指定高度和宽度 */ public static Bitmap getNativeImage(String imagePath) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJu......

Thanks
2012/10/24
615
4
BitmapFactory.Options

@邓凡平 想跟你请教个问题:您好 问一下 BitmapFactory.Options inPurgeable 是什么作用 BitmapFactory.Options 的作用仅限于缓存处理么...

pangbao
2013/07/11
230
1
安卓 图片的压缩 InputStream压缩和Bitmap压缩

对InputStream进行压缩,即con.getInputStream() 对Bitmap压缩

bluecoffee
2015/08/18
67
0

没有更多内容

加载失败,请刷新页面

加载更多

阿里云视频云正式支持AV1编码格式 为视频编码服务降本提效

今天我们要说的 AV1 可不是我们平时说的 .AVI 文件格式,它是由AOM(Alliance for Open Media,开放媒体联盟)制定的一个开源、免版权费的视频编码格式,可以解决H.265昂贵的专利费用和复杂的...

一肥仔
20分钟前
8
0
软件缺陷静态分析 CodeSonar 5.2 新版发布

对于使用C和C++构建安全关键软件的开发团队而言,CodeSonar一直是首选的静态分析解决方案。在近期发行的版本中,CodeSonar通过使用开放标准来扩展其语言覆盖范围,并增加了对Java、C#、Obj...

旋极科技
21分钟前
5
0
数据迁移

1. insert into values 或 insert into select批量插入时,都满足事务的原子性与一致性,但要注意insert into select的加锁问题。 2. replace into与insert into on duplicate key update都可...

qiang123
28分钟前
6
0
Linux装Windows系统后还不会激活?3招教你搞定

     相信大家已经发现荣耀MagicBook科技尝鲜版有多“香”了,不但可以轻松的将Linux系统装回Windows系统,还足足省下了300大洋!但是装回系统就万事大吉了吗?NoNoNo,我们还需要去激活...

梅丽莎好
30分钟前
6
0
Tomcat8源码分析-请求处理过程

上一篇:Tomcat8源码分析-启动流程-start方法 此篇主要讲Tomcat8从接收请求到处理请求的时序图画出来,并用文字描述一下主要流程 时序图 说明 文字描述流程之前先提示如下两点: 1.Acceptor...

特拉仔
32分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部