问题

今天无意中发现了一个问题,通过Bitmap的getWidth和getHeight方法获取到的图片尺寸与实际的尺寸(1920*1080)不一致,后来更进一步发现,把这张图片分别放在raw、drawable-mdpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi、drawable-xxxhdpi时,通过以上两个方法获取到的尺寸也都不一致。

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img_mac_os_x);
if (bitmap != null) {
Log.i("xp.chen", "decode bitmap width: "+bitmap.getWidth()+", bitmap height: "+bitmap.getHeight());
}

下面是把图片分别放在raw、drawable-mdpi、drawable-hdpi、drawable-xhdpi、drawable-xxhdpi、drawable-xxxhdpi时,通过Bitmap的getWidth()/getHeight()分别获取到的尺寸:

raw:I/xp.chen: decode bitmap width: 7680, bitmap height: 4320

drawable-mdpi:I/xp.chen: decode bitmap width: 7680, bitmap height: 4320

drawable-hdpi:I/xp.chen: decode bitmap width: 5120, bitmap height: 2880

drawable-xhdpi:I/xp.chen: decode bitmap width: 3840, bitmap height: 2160

drawable-xxhdpi:I/xp.chen: decode bitmap width: 2560, bitmap height: 1440

drawable-xxxhdp:I/xp.chen: decode bitmap width: 1920, bitmap height: 1080

为什么会这样

首先要知道的是,除了raw文件夹,上述的其它文件夹主要是用来适配不同屏幕的显示密度的,放在不同文件夹里等于是告诉系统,我这张图片是针对哪一种显示密度的设备,如果图片放置的文件夹与实际运行的设备密度不一致,那么系统会对这张图片进行放大或缩小。比如:我把图片放置在xhdpi(dpi是320)里面,但是我实际运行的设备是640,xxxhdpi里又没有放置任何图片,那么这个时候系统就会对放置在xhdpi里的同名图片进行缩放。

BitmapFactory: 通过Bitmap的getWidth和getHeight方法获取到的尺寸与实际尺寸不符的问题-LMLPHP

在屏幕dpi为160时,1dp = 1px,也就是说如果运行设备的屏幕的dpi是160时,图片是可以1:1正常显示的,查看当前屏幕的dpi和density可以通过下列API:

     float density = getResources().getDisplayMetrics().density;
int densityDpi = getResources().getDisplayMetrics().densityDpi;

通过测试,我手机的dpi为640,density是4,也就是说当我把图片放在xxxhdpi里时,图片可以正常匹配,系统不会做任何处理,所以上面放在xxxhdpi时,运行的Log是正确的,刚好是1920*1080,那放置到其它的文件夹里的尺寸是如何计算的呢?个人猜测应该是这样:当放置在

drawable-mdpi时,该文件夹对应的dpi是160,density是1,实际屏幕dpi是640,密度是4,不符合要求,放大4倍 ,(7680*4320);

drawable-hdpi时,该文件夹对应的dpi是240,density是1.5,实际屏幕dpi是640,密度是4,不符合要求,放大2.666 (4/1.5) 倍, (5120*2880);

drawable-xhdpi时,该文件夹对应的dpi是320,density是2,实际屏幕dpi是640,密度是4,不符合要求,放大2 (4/2) 倍, (3840*2160);

drawable-xxhdpi时,该文件夹对应的dpi是480,density是3,实际屏幕dpi是640,密度是4,不符合要求,放大1.333 (4/3) 倍, (2560*1440);

drawable-xxxhdpi时,该文件夹对应的dpi是640,density是4,实际屏幕dpi是640,密度是4,符合要求,正常显示, (1920*1080);

因此导致了使用BitmapFactory在decode图片时发生了上述的差异,那么是否有什么途径可以保证decode图片时,得到的图片尺寸与实际的图片尺寸相一致呢?这里有两种方法:

第一种方法,如果仅仅是为了获取图片的尺寸,不需要获取其对应的Bitmap,可以通过下列方式:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img_mac_os_x, options);
Log.i("xp.chen", "decode bitmap width: "+options.outWidth+", bitmap height: "+options.outHeight);

这里通过 options.outWidth 和 options.outHeight 拿到的就是图片实际的宽高,经测试刚好是1920*1080,注意这里返回的bitmap对象是NULL。

第二种方法,不仅仅是为了要拿到图片的尺寸,也需要拿到对应的Bitmap,可以通过下列方式:

BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img_mac_os_x, options);
if (bitmap != null) {
Log.i("xp.chen", "decode bitmap width: "+bitmap.getWidth()+", bitmap height: "+bitmap.getHeight());
}

设置 options.inScaled 为false,等于告诉系统,不要对该图片进行缩放,通过这种方法拿到的宽高也是1920*1080。

05-20 04:52