当前位置:首页 > 实用技巧 >

手机分辨率dpi怎么算(手机dpi一般设置多少)

来源:原点资讯(www.yd166.com)时间:2024-01-07 04:44:44作者:YD166手机阅读>>

前言

最近线上有用户反馈在App使用过程中遇到大图的时,App异常的卡顿,甚至会出现崩溃的情况。后来排查了一番,发现一个同事在处理图片时,直接原图加载没有做任何“压缩”。这个case的出现,也就引出了这篇文章的必要性。

咱们日常开发过程中,都会使用各种各样的图片库比如Glide。由于所有图片操作都是一股脑的交给图片库去处理,所以即使在遇到大图加载的时候,也无法“复现”这类问题。

因为主流的图片库都帮咱们对大图进行了处理(正印证了那句话:当你能轻松进去的时候,你就该明白,不是你厉害,只是有人在前面替你开路——“鲁讯”)。

既然话都说开了,咱们作为新时代下的福报程序员,那就必须要在这条路上探探深浅。其实图片压缩的方式有很多种,今天咱们只要一种,那就是Google原生的高效加载大图的方案。

正文

进行压缩之前,咱们先来感受一下不压缩会怎样...

一、不压缩,直接加载大图

我随便new了一下项目,搞了一个这样的图:

手机分辨率dpi怎么算,手机dpi一般设置多少(1)

其实也不是特别大,就是一张1080P的图。

然后随便的用一个ImageView去加载一下:

iv.setImageResource(R.drawable.test)

当我尝试run的时候,我高估了我的测试机....没有加载出来,就直接崩了。Logcat也是够直接,无情吐槽:

手机分辨率dpi怎么算,手机dpi一般设置多少(2)

手机分辨率dpi怎么算,手机dpi一般设置多少(3)

这么一张图,一共需要132710400Bytes的内存,也就是132m....等等,不对?!分辨率1080 * 1920的图片怎么可能会使用100 m的内存?

我们都知道,正常一个图片被加载到内存里的文件大小 = 图片分辨率的宽 * 图片分辨率的高 * 色彩格式。带入这个公式内存大小 = 1080 * 1920 * 4 = 7.9m,绝不可能是100 m这么多!

这里可能有朋友会有疑问,为啥JPEG的格式会4,JPEG格式没有alpha通道,不应该占这么大的空间。其实具体几,还是需要看这张图最终Bitmap.Config解出来的值,我这张图解出来是ARGB_8888,所以还是要*4。

如果你也有这个疑问,那么接下来的内容你要好好看咯。这个知识点恐怕是盲区...

二、番外:drawble、drawble-xxhdpi有什么区别

作为一个番外的内容部分。这一章节其实和图片压缩没有什么关系,只是额外聊一聊drawble这个文件夹

上述问题的根本原因就是在于文件放置的位置,我只在drawble文件夹下放置了图片资源。

所以...这种case下,如果加载这个资源的手机是一个高密度屏幕,那么这张图片被展示时,并非1080 * 1920...

接下来咱们来看一看,为什么资源文件随便放会带来这么大的问题!(以下内容,部分来自于官方文档)

手机分辨率dpi怎么算,手机dpi一般设置多少(4)

文档中提到,如果资源提供不当,会导致缩放失真...。这里为什么系统要进行缩放其实也很好理解:

  • 对于系统来说,如果它向下(低密度)才找到需要引用的资源文件,那么最佳的策略便是将找到的图片资源整体放大。因为那里的图,预期是给低分辨率手机准备的。
  • 那么同理,如果系统向上(高密度)找到了需要引用的资源文件,那么缩小无疑是最佳的选择。因为那里的图,预期是给高分辨率手机准备的。

所以基于此,上述中OOM的内存值132710400bytes是这么算出来的:1080 * 4(这个4是手机dpi640 / 资源dpi160 所得) * 1920 * 4 * 4

小贴士:dpi = 手机分辨率长宽各自平方之和开方,除以对角线长度(单位英寸)。 当然我们也可以通过api:resources.displayMetrics.xdpi。这里得到的值就基本等于当前手机的dpi


所以,强制加载这么大的一张图,是不是不负责任!这么大,硬往里塞,搁谁谁受得了?

三、Google提供的解决方案

既然咱们已经明确硬来是不行了,所以还是要采取一些技巧的。文章中开篇就道出了问题的所在:

Images come in all shapes and sizes. In many cases they are larger than required for a typical application user interface (UI). For example, the system Gallery application displays photos taken using your Android devices's camera which are typically much higher resolution than the screen density of your device.

Given that you are working with limited memory, ideally you only want to load a lower resolution version in memory. The lower resolution version should match the size of the UI component that displays it. An image with a higher resolution does not provide any visible benefit, but still takes up precious memory and incurs additional performance overhead due to additional on the fly scaling.

简单翻译一下就是:太大就不要硬塞,缩到合适的尺寸再塞

文档里还有比较有意思的一句话:There are several libraries that follow best practices for loading images. You can use these libraries in your app to load images in the most optimized manner. We recommend the Glide

官方推荐,最为致命

其实文档中直接贴出了可以Ctrl C/V就能使用的代码:

imageView.setImageBitmap( decodeSampledBitmapFromResource(resources, R.id.myimage, 100, 100))fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int { // Raw height and width of image val (height: Int, width: Int) = options.run { outHeight to outWidth } var inSampleSize = 1 if (height > reqHeight || width > reqWidth) { val halfHeight: Int = height / 2 val halfWidth: Int = width / 2 // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) { inSampleSize *= 2 } } return inSampleSize}fun decodeSampledBitmapFromResource( res: Resources, resId: Int, reqWidth: Int, reqHeight: Int): Bitmap { // First decode with inJustDecodeBounds=true to check dimensions return BitmapFactory.Options().run { inJustDecodeBounds = true BitmapFactory.decodeResource(res, resId, this) // Calculate inSampleSize inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight) // Decode bitmap with inSampleSize set inJustDecodeBounds = false BitmapFactory.decodeResource(res, resId, this) }}

代码很好理解,就是将需要加载的图片,按目标所需的加载尺寸进行一次采样,通过采样的值进行等比缩放。

不过这里有一个有趣的细节:官方的代码里是将采样结果进行了 * 2 ( inSampleSize*=2)。当时通过实战我们会发现, inSampleSize并不一定要传2的幂,传3传5传其他也是有效果的。

文档中提到这么一句话:

Note: A power of two value is calculated because the decoder uses a final value by rounding down to the nearest power of two, as per the inSampleSize documentation.(以2的幂作为计算结果,是根据inSampleSize文档,解码器通过四舍五入到最接近的2的幂来使用最终值。)

按照文档的解释inSampleSize为2/3时,效果一样,毕竟3最接近2的幂的值还是2。当时事实跑起来会发现,2和3的结果并不一样:

手机分辨率dpi怎么算,手机dpi一般设置多少(5)

当inSampleSize = 3时,图片长和宽就是比减少了3倍...所以真是不知道官网的葫芦里卖的什么药。

尾声

到这,该唠的基本也就唠完了...内容并不深奥,但也算是必备的知识点~

栏目热文

手机分辨率还有dpi一般是多少(手机dpi高好还是低好)

手机分辨率还有dpi一般是多少(手机dpi高好还是低好)

在当前的主流摄影圈内,一亿像素是个让人恐怖的数字,哈苏H6D-400C据说可达4个亿,但它的价格也像像素一样让人恐怖,网...

2024-01-07 05:12:18查看全文 >>

qq不支持本地查看文件怎么办

qq不支持本地查看文件怎么办

如何解决抖音不识别本地音乐有很多朋友都想用自己剪辑的音乐或者抖音没有的音乐用来做小视频的背景音乐。方法很简单,在新版本中...

2024-01-07 04:46:47查看全文 >>

qq文件怎么本地打开(qq文件怎么用其他方式打开)

qq文件怎么本地打开(qq文件怎么用其他方式打开)

腾讯文档客户端3.0发布,无论何时何地,都能畅享强大的Office功能,一站式便捷处理各种格式文件。全新升级的腾讯文档客...

2024-01-07 05:28:00查看全文 >>

怎么修改qq里面打开文件的位置(qq怎么把打开文件方式换了)

怎么修改qq里面打开文件的位置(qq怎么把打开文件方式换了)

第一步 登录QQ第二步 鼠标点击左下角,出现菜单找到设置点击,出现如下:第三步 点击文件管理 ,出现文件存储位置(QQ所...

2024-01-07 05:08:58查看全文 >>

qq如何设置文件直接打开(怎样设置qq中的文件直接打开)

qq如何设置文件直接打开(怎样设置qq中的文件直接打开)

简介:大家知道,可以通过QQ传输文件。点击下载后,按钮会发生变化。工具:电脑QQ如图:这是朋友发过来的文件,按钮有“下载...

2024-01-07 05:15:40查看全文 >>

手机dpi计算方式(手机默认dpi一般为多少)

手机dpi计算方式(手机默认dpi一般为多少)

1.为什么适配(1) 厂商多,设备多, 屏幕的尺寸, 分辨率多.(2) 大多数的计算方式:dpi等于(屏幕宽的平方 屏幕...

2024-01-07 05:18:06查看全文 >>

手机屏幕ppi和dpi是什么(手机屏幕dpi调多少最好)

手机屏幕ppi和dpi是什么(手机屏幕dpi调多少最好)

「 BK老师包装印刷知识频道 」 第09课= DPI与PPI的区别 =上一篇讲了RGB和CMYK的区别,今天再来讲两个容...

2024-01-07 04:59:50查看全文 >>

网络电视不显示首页怎么回事(网络电视显示没有资源怎么解决)

网络电视不显示首页怎么回事(网络电视显示没有资源怎么解决)

每天很辛苦的更文,发出去的时候满怀期待,期待再次打开的时候出现在首页,但是每次打开,总是以失落结尾。你的心态很好,知道这...

2024-01-07 04:44:48查看全文 >>

网络电视加载不出来怎么办(网络电视一直加载不出来怎么回事)

网络电视加载不出来怎么办(网络电视一直加载不出来怎么回事)

家里的智能电视看不了网络电视是什么原因?如果是没法看点播节目,那建议检查一下网络状况,如果是不知道怎么看电视台节目,那就...

2024-01-07 04:50:01查看全文 >>

文档排行