Android 项目图片资源文件的使用,适配以及优化

Aandroid,适配,bitmap,bitmapfactory,优化,

2016-05-13 16:52:50

Android 项目中常见的图片文件格式

png 支持 alpha 通道,无损压缩,体积大,

jpg 不支持 alpha 通道,有损压缩,体积小,

计算机颜色常见的表达方式:ARGB,一个像素点的颜色由四个信息组成,A 是 Alpha,透明度,也称通透度。RGB 分别值 Red,Green,Blue 三颜色。ARGB 是一种颜色模式,颜色模式有很多种,png 使用的是 ARGB,也可以是 RGB(就是不包含 alpha 通道),jpg 使用的是 YUV 颜色模式。具体的区别可以去研究各种图形文件格式的标准定义。

jpg 是一种有损压缩格式,有损是因为它存储的是 YUV 颜色,也就是它在文件里存储的不是 RGB 颜色,在解码图片的时候,从文件中读取出数据,然后根据一定的算法,换算成 ARGB,这里肯定会有一些精度的损失。压缩模式也有很多种,一种是顺序式压缩,图像的信息从左到右,从上到下,采用这种压缩模式的图片,可以实现从上到下的加载显示方式;另外一种是递增式压缩,可以实现从模糊到清晰的渐进式加载。所以在 Android 项目中,如果想要实现渐进式加载,对要加载的图片还是有一些要求的。如果不是采用类似于递增式压缩的图片,是很难实现渐进式的加载实现的,即使实现了也是有悖初衷的。

文件结构

基本上,任何文件都包含头信息和文件主体。这个是计算机世界上通用的设计,包括文件和协议,都有头和主体(header & body)。

每个文件的前几个字节会标识文件的类型,比如Java 的 class 文件,前四个字节的内容是CAFE,在打开文件的时候,先读取前几个字节,判断该文件是不是当前程序能处理的格式。文件名的后缀不属于文件的内容,而属于文件系统(File System)。

除了前几个字节用来标识文件格式外,接下来的那些内容,直到文件的主体内容前,都被称为头信息,也可以称为 metadata 。每种文件都会定义字节的 metadata 信息,对于图片文件,metadata 会包含咱们最关心的图片大小,只需要解析头信息,就可以知道图片的大小了,于是咱们在使用 BitmapFactory.decode()的时候会推荐这样使用:

BitmapFactory.Options options = new BitmapFactory.Options();

options.inJustDecodeBounds = true;

BitmapFactory.decodeFile(path, options);

这个时候 BitmapFactory 只读取图片的文件的头部的信息,所以返回的 bitmap 对象是空的,在获取到图片的宽高后,在根据比例去 decode 。

适配以及优化

我们知道,在 Android 开发中,有多个不同的 drawable 目录,这些目录的作用是为了做 Android 多分辨率适配的。除了默认的 drawable 目录外,还有 drawable-ldpi,drawable-mdpi 和 drawable-hdpi 。只是 Android 早期版本为三个不同密度屏幕设计的目录,后来又新增了 drawable-xhpi 和 drawable-xxhpi 以及 drawable-xxxhdpi。三个 x 的屏幕密度已经是相当高了,目前高端的手机有不少是这个屏幕密度的。而那些低密度屏已经慢慢的淡出了大家的视线。

mdpi 的屏幕密度为 160dpi

hdpi 的屏幕密度为 240dpi,为 mdpi 的 1.5 倍

xhdpi 的屏幕密度为 320dpi,为 mdpi 的 2 倍

xxhdpi 的屏幕密度为 480dpi,为 mdpi 的 3 倍

xxxhdpi 的屏幕密度为 640dpi,为 mdpi 的 4 倍

适配第一原则

适配的作用就是为了在不同分辨率,不同密度的屏幕上,都能看到我们期望的质量的图像。所以在有图像质量要求的场景下,该放哪个目录放哪个,该放几个放几个。

资源图片对 APK 文件大小的影响

每增加一个资源文件,APK 文件的大小的增大是可以肯定的。而实际上,一个资源图片被打包的时候,打包器还是会对资源进行一些优化的,但是由于 png 和 jpg 已经采用很高的压缩率的编码方式,所以这个优化只能说是很小的,你基本可以认为你增加的大小是约等于文件的大小的。

对应用程序安装后占用空间大小的影响

一直以来,我认为 Android 在安装 APK 文件的时候,不是简单的解压释放文件那么简单,会根据当前设备的一些信息,放弃一些资源文件,比如一张图片在不同的 drawable 目录下都存在,那么只会保留最适配的那张。但是,事实不是这样的。我增加了一张适配文件,安装后的体积还是增加了。

对运行时内存的影响

首先,一个图片资源最终显示在屏幕上的面积会影响其占用的内存大小。在其他条件相同的情况下,一个 200dp 宽高的 ImageView 会比一个 100dp 的占用内存多。

其次,在不考虑显示效果的情况下,最终显示面积相同的控件,其资源文件在低密度下比在高密度下占用内存高。比如一张背景图片被放在 drawable-ldpi 比放在 drawable-xxxhdpi 下占用的内存多。

在不指定 ImageView 控件大小的情况下,资源图片放在低密度目录下,最终显示面积会更大一些,资源图片放在高密度目录下,最终显示面积会变得更小。

在指定的 ImageView 控件大小的情况下,资源图片放在低密度目录下要更加清晰一些,放在高密度目录下,图像会变得模糊。

多出来的 mipmap 目录

在 Android 4.2 后,在使用 Android Studio 创建项目的时候,突然悄悄多了几个 mipmap 的目录,而里面一般只是放了一个应用的启动的图片,那么我们怎么使用这个目录呢,mipmap 和 drawable 有啥不同?

首先看看官方文档的说明:

Mipmapping for drawables

Using a mipmap as the source for your bitmap or drawable is a simple way to provide a quality image and various image scales, which can be particularly useful if you expect your image to be scaled during an animation.

Android 4.2 (API level 17) added support for mipmaps in the Bitmap class—Android swaps the mip images in your Bitmap when you've supplied a mipmap source and have enabled setHasMipMap(). Now in Android 4.3, you can enable mipmaps for a BitmapDrawable object as well, by providing a mipmap asset and setting the android:mipMap attribute in a bitmap resource file or by calling hasMipMap().

就是说 mipmap 和 drawable 功能是相似的,那么怎么使用:

drawable/

For bitmap files (PNG, JPEG, or GIF), 9-Patch image files, and XML files that describe Drawable shapes or Drawable objects that contain multiple states (normal, pressed, or focused). See the Drawable resource type.

mipmap/

For app launcher icons. The Android system retains the resources in this folder (and density-specific folders such as mipmap-xxxhdpi) regardless of the screen resolution of the device where your app is installed. This behavior allows launcher apps to pick the best resolution icon for your app to display on the home screen. For more information about using the mipmap folders, see Managing Launcher Icons as mipmap Resources.

在目前为止,大部分场景下,咱们不需要把图片放在 mipmap 目录下。

Bitmap

对于 Android 开发来说,由于 bitmap 的问题导致的 OOM 是咱们平时开发中需要注意的事情。当然,一般项目的中使用的框架已经基本上 hold 住这些问题了。

在 Bitmap 类中,封装了一个 byte[] ,就是这个 byte[] 占用了大量的内存。

比如手机拍摄的是一个 3000 × 4000 像素的图片,而咱们需要在屏幕上显示一个很小的缩略图。如果这张图片经过了 Android 系统的扫描,系统会为这张图生成一套缩略图,我们可以直接使用这套缩略图。而如果这套缩略图不符合咱们需要,或者系统没有扫描这张大图,那么我们需要自己去 decode 这张图片。如果我们直接去 decode 这张图,那么咱们将会占用 3000×4000×4 = 45.78 Mb 的内存,这样是很危险的。在上文中,咱们说了一种办法来减少 bitmap 的内存占用,先 decode 图片的头信息,获得宽和高后,在按比例去 decode 图片。在获得图片的原始宽高后,又假设咱们的手机屏幕是 720 宽的,在第二次 decode 的时候,BitmapFactory 会根据 options 对象的 inSampleSize 参数来等比例缩小图片,inSampleSize = 2 表示宽和高各取二分之一。很不幸,inSampleSize 只能是一个整数,而且只能是 2 的 N 次方。如果 inSampleSize = 4 ,宽和高分别为原始图片的四分之一,也就是 750 × 1000,这个大小是比较符合咱们期望的。如果咱们使用 inSampleSize = 4 去 decode 图片的话,这个时候的内存占用应该会是 750×1000×4 = 2.9 Mb,也就是刚才 45.78 的十六分之一,这样一下子就减少了很多内存占用了。咱们可以再进一步对 750 进行缩放,或者直接使用都是可以的。上面计算的时候,每个像素点都是以 4 个字节的占用去计算的,在使用 BitmapFactory decode 图片的时候,我们还可以通过设置 options 对象的 inPreferredConfig 参数来指定每个像素占用的字节数,默认是 ARGB_8888,也就是 4 个字节,如果我们设置为 RGB_565,则每个像素占用的是 2 个字节,这样内存占用还能再减少一半,也就是 1.45 Mb。在 Bitmap 类中,封装了一个 byte[],默认情况下,这个数组的每四个单元用来表示一个像素点的颜色值,在使用 RGB_565 的情况下,这个数组的每两个单元用来表示一个像素点的颜色值。

所以,在咱们使用 BitmapFactory 手动 decode 图片的时候,需要咱们关心的参数就是 options.inSampleSize 和 inPreferredConfig ,这两个参数会影响到 bitmap 的体积,同样也会影响到图像的质量。

相关文章

- EOF -

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处,尊重他人劳动。

转载请注明:文章转载自 Binkery 技术博客 [https://binkery.com]

本文标题: Android 项目图片资源文件的使用,适配以及优化

本文地址:https://binkery.com/archives/556.html

Android中图片资源格式的是,Android 项目图片资源文件的使用,适配以及优化相关推荐

  1. 软件android_id,Android中@id和@+id及@android:id的区别介绍

    前言 昨天突然有新来的同事问我这个@id 和@+id 的区别 ,为什么 我们的项目都是@id 自己新增的ui 使用的@+id 这里说下我的简单的回复项目是维护的之前的是为了统一管理使用了@id  方便 ...

  2. android支持svg格式图片么,Android Studio2.0中使用SVG图片格式

    SVG格式, 适应屏幕, 图片较小, 还有很多优点 . 本文讲解如何使用SVG格式. SVG: Scalable Vector Graphics, 可缩放矢量图形. IRI: Internationa ...

  3. 使用gradle构建android项目,Android中使用Gradle来构建App项目的入门指南

    gradle是Android开发中引入的全新的构建系统,因为全新的构建系统主要是出于下面的目的: 1. 方便复用代码和资源 2. 构建多种版本的apk更见简单,不论是为多渠道构建不同的apk还是构建不 ...

  4. android打开wav格式,FileNotFoundException从Android资产中打开wav文件

    在我们的android应用程序中,我们打开位于assets/config/notification.wav中的wav文件.要打开和播放声音,我们使用下面的代码:FileNotFoundExceptio ...

  5. android 英文日期格式,国际化-基于Android上用户区域设置的日期格式

    当提出问题时,虽然可接受的答案是正确的,但后来却过时了. 我正在做出现代答案. java.time和ThreeTenABP DateTimeFormatter dateFormatter = Date ...

  6. android 中如何用aes算法加密解密zip文件,android中AES加解密的使用方法

    今天在android项目中使用AES对数据进行加解密,遇到了很多问题,网上也找了很多资料,也不行.不过最后还是让我给搞出来了,这里把这个记录下来,不要让别人走我的弯路,因为网上绝大多数的例子都是行不通 ...

  7. android中应用程序生命周期,Android应用程序生命周期中的活动和图标

    面向大众的移动技术,第3部分 为您的Android移动应用程序添加导航样式 安德鲁·格洛弗 2013年7月25日发布 面向大众的移动技术 请期待本系列的后续内容. 请期待本系列的后续内容. 近年来,移 ...

  8. Android 中 RegistrantList消息处理机制 以android 5.0 MT为例

    这其实是观察者模式的一种实现形式 先明确两个身份 1.RefistrantList 通知者 2.Registrant 观察者,这是一个一对多的关系,在有事件更新时,凡是在名单上登记过的对象,都会收到通 ...

  9. android中互斥的控件,Android控件之Radiobutton与RadioGroup

    RadioButton 是一个单选控件,在一个RadioGroup中,各个RadioButton是互斥的 XML文件: xmlns:tools="http://schemas.android ...

最新文章

  1. 126篇殿堂级深度学习论文分类整理 从入门到应用 | 干货
  2. spring无法扫描jar包的问题
  3. 一致性代码段和非一致性代码段【转】
  4. 喜欢到底是什么样子呢
  5. centos 6.5安装mysql5.7,centos6.5安装mysql5.7
  6. layout_weight layout_gravity gravity
  7. 7000更换控制器电源步骤_开关电源控制环路(初级篇:上)
  8. 【Python】AttributeError: ‘DatetimeProperties’ object has no attribute ‘weekday_name’ 的解决方法
  9. java 异常处理线程_转:Java子线程中的异常处理(通用)
  10. 计算机主机的奥秘,揭秘网吧电脑为何流畅的奥秘
  11. linux内核disabled,Linux内核关闭IPv6协议的方式
  12. [NIO]dawn之Task具体解释
  13. jaxen.jar下载地址
  14. JS中的debugger调试(谷歌浏览器)
  15. LaTeX技巧353:图片标题的字体大小怎么设定呢?
  16. 5G笔记| 概述:5G三大应用场景、5G关键技术概览
  17. 【融职教育】Web全栈开发就业班核心优势
  18. str.substring() 的用法
  19. 已知一无符号的整数占用了4个字节的内存空间,现欲从低位存储地址开始,将其每个字节作为单独的一个ASCII码字符输出,试用共同体类型实现上述转换。
  20. Paint X for Mac破解教程

热门文章

  1. php wps 读取word内容,PHP-如何使用PHP解析WPS格式的Excel文档
  2. 下载正版Windows系统地址
  3. 变频电源故障:变频电源IGBT烧坏的原因是什么
  4. 2016暑期集训10 C吴传之火烧连营
  5. GBase 8a 告警管理--页面告警
  6. 活动推广的作用有哪些呢?
  7. 成功的秘诀在于长久的坚持和耐心
  8. 计算机流行音乐数字乐谱,求流行歌曲简谱(要数字的,不要发网站过来)
  9. oracle prevsqlid,对v$session的 PREV_SQL_ID的疑问
  10. python邮件定时发送短信_Python趣味编程:如何定时发短信给Ta讲笑话