`
1025250620
  • 浏览: 229841 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[转]Android编程之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)
  开始不太理解,所以,看完代码后,先做了个实验,在三个文件夹下分别放入图片,通过下面的测试代码:
view sourceprint?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中的实现:
view sourceprint?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方法:
view sourceprint?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),其中,有在创建返回图片时设置缩放比例的计算:
view sourceprint?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的一致,就可以避免缩放了,所以,我封装了一个解析函数:
view sourceprint?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);
}
这样,无论图片放在哪个文件夹里,都可以不必担心会被缩放了。
分享到:
评论

相关推荐

    Android对图片进行变换操作的代码例子

    我们可以使用` BitmapFactory `类的静态方法,如`decodeResource()`或`decodeFile()`来从资源或文件路径加载图片到Bitmap对象。例如: ```java Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R....

    android 缩放图片上添加文字

    - 加载图片:通常我们使用` BitmapFactory.decodeResource()` 或 ` Glide / Picasso` 等库来加载图片到Bitmap对象。 - 创建可变Bitmap:为了避免原始Bitmap是不可变的,我们需要创建一个可变的Bitmap副本,使用 `...

    android 图片放大缩小 有图

    在Android开发中,图片的放大和缩小是一个常见的需求,特别是在用户界面设计和图像处理中。Android提供了多种方式来实现图片的缩放操作,这通常涉及到Bitmap对象和ImageView组件的使用。下面将详细介绍Android图片...

    Android应用源码BitmapFunc.zip

    decode*方法可以根据不同的源解析出Bitmap,例如decodeResource()用于从资源文件加载,decodeFile()用于从本地文件加载。 3. **内存管理与优化**:Bitmap占用了大量内存,不当使用可能导致内存溢出。使用...

    安卓开发入门之图片缩放(翻译)

    我们可以通过BitmapFactory.decodeResource()方法从资源中加载图片,然后使用Bitmap.createScaledBitmap()进行缩放。此方法接受源Bitmap、目标宽度和高度作为参数,可以实现按比例缩放。注意,不正确的缩放可能导致...

    Android Image各种效果处理-IT计算机-毕业设计.zip

    例如,使用`BitmapFactory.decodeResource()`从资源文件加载图片,使用`Bitmap.createScaledBitmap()`进行缩放,`Bitmap.createBitmap()`创建新Bitmap,以及`Matrix`进行旋转和翻转。 2. **滤镜效果**:源码可能...

    android 画图片的几种方法

    在Android开发中,绘制图片是一项常见的任务,可以用于创建用户界面、实现自定义视图或者进行图形编程。本文将深入探讨几种在Android中绘制图片的方法,结合提供的资源和标签,我们将涵盖源码解析以及可能涉及的工具...

    Android之实现截图,圆形,Canvas功能_图片处理.zip

    这个自定义的`CircleImageView`会将加载的图片裁剪为圆形,并在`onDraw()`方法中绘制。 最后,`Canvas`是Android图形系统的核心组件,用于在Bitmap或其他图形表面进行绘图操作。它可以画线、矩形、圆、文字等,还...

    Android 图片圆弧 和 圆形

    此外,使用`BitmapFactory.Options`来缩放图片,避免加载不必要的大尺寸图片。 6. **兼容性问题** 考虑到Android设备的多样性,确保你的代码在不同版本的Android系统上都能正常工作。对于API等级较低的设备,可能...

    本示例 演示可任意改变透明度的位图

    1. 加载位图:使用`BitmapFactory.decodeResource()`或`BitmapFactory.decodeFile()`等方法从资源或文件加载位图。 2. 获取位图的Alpha通道:使用`Bitmap.copy()`方法创建位图的副本,并设置配置为`Bitmap.Config....

    Android编程之图片相关代码集锦

    在Android编程中,图片处理是常见且重要的任务。本文将探讨一些关键的代码片段,涉及Bitmap、String、Drawable之间的转换,以及如何进行简单的图片处理。 1. **Bitmap转化为字符串**: 这个方法用于将位图(Bitmap...

    Android裁剪图片为圆形图片Demo

    以下我们将详细介绍如何在Android中裁剪图片为圆形,并提供相关的编程知识点。 1. **圆形图片的实现方式** 在Android中,最常用的方法是通过自定义`ImageView`来实现。首先,创建一个继承自`ImageView`的新类,...

    Android高级应用源码-安卓图片旋转放大缩写透明度调整例子.zip

    3. **图片缩放**:同样,`Matrix`类也可以用于缩放图片,通过设置`postScale()`方法,传入水平和垂直的缩放比例。 4. **透明度调整**:在Android中,`Paint`类的`setAlpha()`方法可以用来设置绘制图片时的透明度,...

    android example

    使用`BitmapFactory.decodeResource()`或`BitmapFactory.decodeFile()`可以加载图片资源或本地文件到Bitmap对象。一旦有了Bitmap,可以通过Canvas进行绘制,也可以使用`Bitmap.createBitmap()`创建新的Bitmap或用`...

    BitmapFun_Android.rar

    在Android中,通常通过` BitmapFactory`类来解码图片文件并创建Bitmap实例。`decodeResource()`用于从资源文件加载,`decodeStream()`则适用于网络流。 2. **内存管理**:由于Bitmap占用大量内存,不恰当的使用可能...

    android 9.0关于桌面壁纸出现黑边的问题

    - **缩放**:使用`Bitmap.createScaledBitmap()`方法可以将图片缩放到适合屏幕的大小,避免黑边。 - **裁剪**:若图片过大,可以先用`Bitmap.createBitmap()`裁剪出合适部分,再设置为壁纸。 - **处理宽高比**:...

    Android编程实现只显示图片一部分的方法

    在这个类中,我们首先通过`BitmapFactory.decodeResource()`方法加载图片资源,例如`R.drawable.girl`。接着,获取屏幕的宽度和高度,以便后续计算图片的缩放比例。 获取到图片的原始宽度和高度后,我们可以计算出...

    给图片添加水印

    这通常涉及到` BitmapFactory.decodeResource() `方法,用于从资源文件加载图片。 2. **创建水印**:水印可以是文本或图像。对于文本水印,我们可以使用`Canvas`对象绘制`Paint`实例,设置合适的字体、颜色和透明度...

    Android编程之书架效果背景图处理方法

    1. 在myGridView的构造函数中,通过BitmapFactory.decodeResource加载背景图片资源(R.drawable.bookcase_bg)。 2. 在dispatchDraw()方法中,获取背景图片的原始宽度和高度,以及手机屏幕的当前宽度和高度。 3. ...

    android 图片剪切

    这通常通过`BitmapFactory.decodeResource()`方法完成,传入资源ID即可。为了避免内存溢出,应使用`options.inJustDecodeBounds`来获取图片尺寸,然后根据屏幕大小调整缩放比例。 3. **ImageView与Matrix** `...

Global site tag (gtag.js) - Google Analytics