android加载图像资源大小改变问题

来源:互联网 发布:河西学院网络教学平台 编辑:程序博客网 时间:2024/06/04 19:33

BitmapFactory.decodeResource(?,?)这个带两个参数的方法:第一个参数是包含你要加载的位图资源文件的对象(一般写成 getResources()就ok了);第二个时你需要加载的位图资源的Id。BitmapFactory.decodeResource(?,?,?)带三个参数的方法:前两个和上面的方法一样。第三个参数应该是对你要加载的位图是否需要完整显示,如果你只需要部分,可以在这里定制。
BitmapFactory.decodeResource加载图片缩小的原因及解决方法

  声明:我是以2.0的代码为参考的,主要参考了BitmapFactory.Java文件。

  首先,在2.0应用中,res下有drawable-hdpi、drawable-mdpi、drawable-ldpi三个存放图片的文件夹,查资料看到如下描述:

    这是分辨率的不同,H是高分辨率 M是中 L是低。    drawable- hdpi、drawable- mdpi、drawable-ldpi的区别:     (1)drawable-hdpi里面存放高分辨率的图片,如WVGA (480x800),FWVGA (480x854)     (2)drawable-mdpi里面存放中等分辨率的图片,如HVGA (320x480)     (3)drawable-ldpi里面存放低分辨率的图片,如QVGA (240x320)

  开始不太理解,所以,看完代码后,先做了个实验,在三个文件夹下分别放入图片,通过下面的测试代码:

?
private int getTargetDensityByResource(Resources resources, int id) {
    TypedValue value = new TypedValue();
    resources.openRawResource(id, value);
    Log.d("LuoYer""value.density: " + value.density);
    return value.density;
}

  分别调用三个文件夹中的资源,打印分别为:240、160、120.

  为什么看这个值呢?先看看我们调用的decodeResource方法在BitmapFactory.java中的实现:

?
public static Bitmap decodeResource(Resources res, int id, Options opts) {
    Bitmap bm = null;
    InputStream is = null;
    try {
        final TypedValue value = new TypedValue();
        is = res.openRawResource(id, value);
        bm = <strong>decodeResourceStream</strong>(res, value, is, null, opts);
    } catch (Exception e) {
    } finally {
        try {
            if (is != null) is.close();
        } catch (IOException e) {}
    }
    return bm;
}

 接着看decodeResourceStream方法:

?
public static Bitmap decodeResourceStream(Resources res, TypedValue value,
        InputStream is, Rect pad, Options opts) {
    if (opts == null) {
        opts = new Options();
    }
    if (opts.inDensity == 0 && value != null) {
        final int density = value.density;
        if (density == TypedValue.DENSITY_DEFAULT) {
            opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
        } else if (density != TypedValue.DENSITY_NONE) {
            opts.inDensity = density;
        }
    }
    if (opts.inTargetDensity == 0 && res != null) {
        opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
    }
    return decodeStream(is, pad, opts);
}

里面用到了value的density值来判断opts的inDensity的设置。

所以说,当我们从三个文件夹中获取资源的时候opts.inDensity的值分别会被设置成240、160、和120.

decodeResourceStream方法在对opts.inDensity设置之后,又进行了opts.inTargetDensity的设置,当其值为0的时候,会对其赋值。

如果,在测试函数中加入Log.d("LuoYer", "densityDpi: " + resources.getDisplayMetrics().densityDpi);在我的板子上会打印值160.

那么,opts的inDensity和inTargetDensity 对解析图片有什么关系呢?

通过decodeStream方法,最后会调用到finishDecode方法(此处仅列出计算示意,详细代码请查看BitmapFactory.java),其中,有在创建返回图片时设置缩放比例的计算:

?
final int density = opts.inDensity;
 
final int targetDensity = opts.inTargetDensity;
 
float scale = targetDensity / (float)density;

最后的scale,就是缩放比例了,所以说,如果我们把图片资源放在了drawable-hdpi中,opts.inDensity的值为240,

而opts.inTargetDensity为0的情况下,会被设置为160. 这样,返回的图片就会按2/3(160/240)的比例被缩放了。

而在drawable-mdpi中的图片,就不会被缩小。

当然,这也是以resources.getDisplayMetrics().densityDpi的值为基础的。

==============================================================================

原因已经清楚了,那么,怎样解决呢?

有看到说:把图片放到drawable-mdpi中就可以了。 当然,在我前面叙述的情况下是可以的,但如果resources.getDisplayMetrics().densityDpi的值变化了,还会产生缩放的情况。

由于最后的图片创建用到了scale,那么,我们只需要保持density和targetDensity的一致,就可以避免缩放了,所以,我封装了一个解析函数:

?
private Bitmap decodeResource(Resources resources, int id) {
    TypedValue value = new TypedValue();
    resources.openRawResource(id, value);
    BitmapFactory.Options opts = new BitmapFactory.Options();
    opts.inTargetDensity = value.density;
    return BitmapFactory.decodeResource(resources, id, opts);
}

这样,无论图片放在哪个文件夹里,都可以不必担心会被缩放了。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 备孕子宫内膜厚怎么办 有成熟卵泡不破怎么办 卵泡不排萎缩了怎么办 卵泡8mm一直不长怎么办 卵泡已经长到28x19mm怎么办 多囊卵巢卵泡长不大怎么办 优势卵泡19不排怎么办 多囊卵泡不排卵怎么办 卵泡两天长2mm怎么办 子宫小43*38*26怎么办 优势卵泡打破卵针后并不破怎么办 ktv禁止自带酒水怎么办 记名西瓜卡丢了怎么办 日本电车卡丢了怎么办 网贷暂时没钱还怎么办 华泰倒闭了汽车怎么办 猫躲起来找不到了怎么办 狗生病了不吃饭怎么办 猫猫托运后害怕怎么办 新来的猫害怕怎么办 升工资老板不公平对待怎么办 自酿啤酒苦味重怎么办 自酿啤酒酸味重怎么办 微信电话费充错了怎么办 支付宝电话费充错了怎么办 在淘宝上充错电话费了怎么办 话费1000充错了怎么办 东西掉在地铁上怎么办 高铁安检丢东西怎么办 东西掉成都地铁上怎么办 东西掉在成都地铁上怎么办 成都地铁上掉东西了怎么办 地铁站丢了东西怎么办 在地铁站丢了东西怎么办 没有签劳动合同不发工资怎么办 没有劳动合同辞职不给工资怎么办 地铁安检要交押金怎么办 在广州地铁上人走丢了怎么办 海尔全自动洗衣机程系乱了怎么办 河南危险化学品经营许可证怎么办 甲方不给付监理费怎么办