`
1025250620
  • 浏览: 225371 次
  • 性别: 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.Options使用方法详解

    BitmapFactory.Options的使用是在加载图片时,就从图片的加载和使用说起  怎样获取图片的大小? 首先我们把这个图片转成Bitmap,然后再利用Bitmap的getWidth()和getHeight()方法就可以取到图片的宽高了。 新问题又...

    Android代码-一个酷炫的分享控件

    What's FlipShare ? It's a cool way to show share widget. Demo Usage step 1. Confirm your parentView to ... .addItem(new ShareItem("Twitter", Color.WHITE, 0xff4999F0, BitmapFactory.decodeResource(ge

    BitmapFactory.Options

    BitmapFactory.Options

    Android Bitmap的加载与缓存

    SDK提供了BitmapFactory类供我们加载图片,常用的方法有这么几个: BitmapFactory.decodeFile :从文件加载。 BitmapFactory.decodeByteArray :从字节数组加载。 BitmapFactory.decodeStream :从输入流加载。 ...

    CircularImageView-Xamarin-:圆形 ImageView 和 Drawable、Xamarin Android 库和示例项目

    Bitmap bitmap = BitmapFactory.DecodeResource (Resources, Resource.Drawable.sample); CircularDrawable d = new CircularDrawable (bitmap, (int)UiUtils.ConvertDpToPx (ApplicationContext, margin), ...

    GLRippleView-Android 水波涟漪图片特效 绝对震撼.zip

     BitmapFactory.decodeResource(resources, R.drawable.bg2),  BitmapFactory.decodeResource(resources, R.drawable.bg3)  ))  setRippleOffset(0.01f)  setFadeInterval(5000)  ...

    android内存优化之图片优化

    尽量不要使用setImageBitmap、setImageResource、BitmapFactory.decodeResource来设置一张大图,因为这些方法在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存。因此,改用先通过...

    ImageCoverFlow-效果不错的画廊控件 可以设置画廊一次可见图片的张数.zip

    介绍:效果不错的画廊控件 可以设置画廊一次可见图片的张数,和其他第三方Gallery控件不同的是,该控件直接继承自View,而不是sdk中的Gallery控件。如果想获得包含demo的可运行代码,请在本站的下载链接中下载。项目...

    BitmapFactory_Delegate.rar_android

    Delegate implementing the native methods of android.graphics.BitmapFactory.

    Android代码-NextQRCode

    final Bitmap centerImage = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); // 生成的二维码图案 Bitmap qrCodeImage = new QRCodeEncoder.Builder() .width(size) // 二维码图案的宽度...

    opencv_android开发库

    Bitmap bm1 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); double scale = 0.1; imageView.setImageBitmap(bm1); Mat img = Highgui.imread("/sdcard/test.png", 0); org....

    Bitmap生成时序图

    这是博文《BitmapFactory.decodeResource VS BitmapFactory.decodeStream》中的时序图,发现上传后,看不清楚,所以上传在这里。

    Android 使用内置的Camera应用程序捕获图像

    加载并显示一副图像对内存使用情况有显著的影响,Android提供了一个名为BitmapFactory 的实用程序类,该程序提供了一系列的静态方法,允许通过各种来源加载Bitmap图像。针对我们的需求,将从文件加载图像,并在最初...

    Android加载图片内存溢出问题解决方法

    在将图片转换成Bitmap的时候,由于图片的大小不一样,当遇到很大的图片的时候会出现超出内存的问题,为了解决这个问题Android API提供了BitmapFactory.Options这个类. 2. 由于Android对图片使用内存有限制,若是...

    ViewPager或ImgeView加载图片出现内存溢出(OOM)

    解决方案:改用先通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source。decodeStream最大的优势在于其直接调用nativeDecodeAsset()来完成decode,无需再使用java层的createBitmap...

    android加载大图

    由于android内存的限制,andoid系统给每个应用分配的内存是有限的,当直接加载一个占用内存加大的图片时就会发生OOM. 一、降采样大图 主要是利用BitmapFactory.Options对象的inSampleSize参数,根据空间尺寸与大图...

    avatar-android-可生成圆形、方形、及方形的组合头像.zip

    可生成圆形、方形、及方形的组合头像。项目地址:https://github.com/Pedroafa/avatar-android 效果图:如何使用:首先创建个ImageView  android:id="@ id/roundedAvatar"  android:layout_height="fill_parent...

    Android图像数字识别

    Bitmap mp = BitmapFactory.decodeResource(getResources(), R.drawable.number1); mp = mp.copy(Bitmap.Config.ARGB_8888, false); baseApi.setImage(mp); String value = baseApi.getUTF8Text(); 需要,...

    生成带有logo的二维码 ZXingDemo

    logoBmp = BitmapFactory.decodeResource(getResources(), R.mipmap.demo); //通过ZXing框架将地址和logo图片加到里面,生成二维码之后赋值给codeBmp; codeBmp = ZXingUtilsTest.createQRImage(this, url, ...

Global site tag (gtag.js) - Google Analytics