- Bitmap描述:
每一张图片都是有无数点组成,我们取其中足够数量的点(可以形成视觉连贯性,以便形成近似真正图片的视觉效果),这些点就是像素点。比如某张图片大小为:1080*1920 ,它的像素数就为1080*1920个。这些像素点的信息就是这张图片的表述。
每个像素的信息,就是ARGB四个通道的值。其中,A代表透明度,RGB代表红绿蓝三种颜色通道值。每个通道的值范围在0~255之间,即有256个值,刚好可以通过一个字节(8bit)进行表示。所以,每个通道值由一个字节表示,四个字节表示一个像素信息。
- 在这里需要注意两点:
1)在实际需求中,有的时候,我们并不需要这么丰富的颜色数量,所以可以适当减少表示每个颜色通道的bit位数。这么做的好处是节省空间。也就是说,每个颜色通道都采用8bit来表示是代表全部颜色值的集合;而我们可以采用少于8bit的表示方式,尽管这会缺失一部分颜色值,但是只要颜色够用即可,并且这还可以节省内存空间。
2)如果我们需要某个图片作为背景或者图标,这个图片透明度A通道值是必要的。但是如果我们只是普通的图片展示,比如拍摄的照片,透明度值毫无意义。因此,透明度这个通道值是否有必要表示也是根据需求自由变化的。
- Bitmap.config:
Config是Bitmap的一个枚举内部类,它表示的就是每个像素点对ARGB通道值的存储方案。取值有以下四种:
ARGB_8888:这种方案就是上面所说的每个通道值采8bit来表示,每个像素点需要4字节的内存空间来存储数据。该方案图片质量是最高的,但是占用的内存也是最大的
ARGB_4444:这种方案每个通道都是4位,每个像素占用2个字节,图片的失真比较严重。一般不用这种方案。
RGB_565:这种方案RGB通道值分别占5、6、5位,但是没有存储A通道值,所以不支持透明度。每个像素点占用2字节,是ARGB_8888方案的一半。
ALPHA_8:这种方案不支持颜色值,只存储透明度A通道值,使用场景特殊,比如设置遮盖效果等。
比较分析:一般我们在ARGB_8888方式和RGB_565方式中进行选取:不需要设置透明度时,比如拍摄的照片等,RGB_565是个节省内存空间的不错的选择;既要设置透明度,对图片质量要求又高,就用ARGB_8888。
- Bitmap的压缩存储
Bitmap是图片内容在内存中的表示形式,那么如果想要将Bitmap对象进行持久化存储为一张本地图片,需要对Bitmap对象表示的内容进行压缩存储。根据不同的压缩算法可以得到不同的图片压缩格式(简称为图片格式),比如GIF、JPEG、BMP、PNG和WebP等。而从存储中读取Bitmap对象,则是解压缩过程。
这样的目的是:当图片持久化保存在磁盘上时,我们应该尽可能以最小的体积来保存同一张图片的内容,这样有利于节省磁盘空间;而当图片加载到内存中以显示的时候,应该将磁盘上压缩存储的图片内容完整地展开。前者即为压缩过程,目的是节省磁盘空间;后者即为解压缩过程,目的是在内存中展示图片的完整内容。
一般压缩可分为:有损压缩和无损压缩:
1)无损压缩基本原理是:相同的颜色信息只需保存一次。具体过程是:首先会确定图像中哪些区域是相同的,哪些是不同的。包括了重复数据的区域就可以被压缩,只需要记录该区域的起始点即可。
从本质上看,无损压缩的方法通过删除一些重复数据,也能在位图持久化存储的过程中减少要在磁盘上保存的图片大小。但是,如果将该图片重新读取到内存中,重复数据会被还原。因此,无损压缩的方法并不能减少图片的内存占用量,如果要减少图片占用内存的容量,就必须使用有损压缩方法
2)有损压缩的原理是:保持颜色的逐渐变化,删除图像中颜色的突然变化。生物学中的大量实验证明,人类大脑会自发地利用与附近最接近的颜色来填补所丢失的颜色。有损压缩的具体实现方法就是删除图像中景物边缘的某些颜色部分,利用有损压缩技术可以在位图持久化存储的过程中大大地压缩图片的存储大小,但是会影响图像质量,这一点在压缩率很高时尤其明显。所以需要选择恰当的压缩率。
对比分析:有损压缩压缩率高而且可以灵能保活设置压缩率,并且删除的数据不可还原,因此可以减少图片的内存占用,但是对图片质量会有一定程度的影响;无损压缩可以很好地保存图片质量,也证一定的压缩率虽然没有有损压缩那么高,并且无损压缩删除的数据在重新加载至内存时会被还原,因此不可以减少图片的内存占用。
几种压缩格式:
1)JPG/JPEG:JPEG/JPG是一种有损压缩格式,JPEG图片以24位颜色压缩存储单个位图。也就是说,JPEG不支持透明通道。JPEG也不支持多帧动画,但JPEG2000作为JPEG的升级版,其压缩率比JPEG高约30%左右,同时支持有损和无损压缩。
2)PNG:
PNG格式也属于无损压缩,其位深为32位,也就是说它支持所有的颜色类型。同样是无损压缩,PNG的压缩率高于Gif格式,而且PNG支持的颜色数量也远高于Gif,因此:如果是对静态图片进行无损压缩,优先使用PNG取代Gif,因为PNG压缩率高、色彩好;但是PNG不支持动画效果。所以Gif仍然有用武之地。PNG缺点是:由于是无损压缩,因此PNG文件的体积往往比较大,APP瘦身时需要对PNG文件进行优化。
3)WBEP:
WebP 是 Google 在 2010 年发布的图片格式,希望以更高的压缩率替代 JPEG。它用 VP8 视频帧内编码作为其算法基础,取得了不错的压缩效果。WebP支持有损和无损压缩、支持完整的透明通道、也支持多帧动画,并且没有版权问题,是一种非常理想的图片格式。WebP支持动图,基本取代gif。WebP不仅集成了PNG、JPEG和Gif的所有功能,而且相同质量的无损压缩WebP图片体积比PNG小大约26%;如果是有损压缩,相同质量的WebP图片体积比JPEG小25%-34%,
它的缺点为:编解码时间长,约为JPEG的8倍左右。
- Bitmap的简单使用
1、Bitmap的加载方法
Bitmap的工厂类BitmapFactory提供了四类静态方法用于加载Bitmap对象:decodeFile、decodeResource、decodeStream、decodeByteArray。
分别代表从本地图片文件、项目资源文件、流对象(可以是网络输入流对象或本地文件输入流对象)、字节序列中加载一个Bitmap对象。
之前讲的图片的三个来源,都可以找到对应的decodeXXXX方法来获取该图片对应的Bitmap对象。
举个例子,假设需要通过网络请求一张图片资源并展示:先处理该网络请求并得到返回结果的输入流对象;依据该流对象调用decodeStream方法得到一个Bitmap对象,该对象即表示这张图片的内容;最后通过ImageView的setImageBitmap()方法显示该图片即可。
2、Bitmap的压缩存储方法
Bitmap的压缩存储与Bitmap的加载是相反的过程,通过compress()方法来实现,该方法原型为:
compress(Bitmap.CompressFormat format, int quality, OutputStream stream)
format参数表示压缩存储的格式,可选为PNG、JPEG和WEBP;quality表示压缩率,取值在0~100之间,100表示未压缩,30表示压缩为原大小的30%,但是该参数在format值为PNG时无效,因为PNG属于无损压缩无法设置压缩率;stream就是希望输出到某个位置的输出流对象,比如某个文件的输出流对象。通过compress()方法可以将Bitmap按照指定的格式和压缩率(非PNG格式时)压缩存储到指定的位置。
3、BitmapFactory.Options类
BitmapFactory是Bitmap的工厂类,通过BitmapFactory的静态方法来创建Bitmap对象;BitmapFactory.Options类代表对Bitmap对象的属性设置(配置)
属性 | 作用 |
boolean inJustDecodeBounds | 是否只获取信息,不加载Bitmap |
int inSample | 采样率 默认1 |
Bitmap.config inPreferredConfig | 色彩模式 |
int outwidth | Bitmap宽 |
int outheight | Bitmao高 |
boolean inDither | 防抖动 默认false |
int inDensity | 像素密度 |
boolean isScaled | 是否可以缩放 默认true |
boolean isMutable | decode方法返回的结果是否可变 |
inJustDecodeBounds:这个属性表示是否只扫描,默认false,值为true时,不会返回Bitmap对象,返回NULL,但会获取宽高等信息。
inSample:默认为1,比如说有一张图片是2048像素X1024像素,那么默认情况下该图片加载到内存中的Bitmap对象尺寸也是2048像素X1024像素。如果采用的是ARGB_8888方式,那么该Bitmap对象加载所消耗的内存为2048X1024X4/1024/1024=8M,如果值为2,则加载结果Bitmap宽高都为1/2,消耗内存为1024X512X4/1024/1024*=2M,如果为4,消耗内存为512X256X4/1024/1024*=0.5M,这极大的节省了内存资源从而避免了OOM错误。
切记:官方对于inSample值的要求是,必须为2的幂,比如2、4、8...等整数值。
inPreferredConfig:该属性指定Bitmap的色深值,该属性类型为Bitmap.Config值。例如你可以指定某图片加载为Bitmap对象的色深模式为ARGB_8888,即:options.inPreferredConfig=Bitmap.Config.ARGB_8888。
isMutable:该属性表示通过decodeXXXX方法创建的Bitmap对象其代表的图片内容是否允许被外部修改,比如利用Canvas重新绘制其内容等
- Bitmap的进阶使用
1)官方推荐计算合理采样率:
基本步骤就是:①获取位图原尺寸 ②获取ImageView即最终图片显示的尺寸 ③依据两种尺寸计算采样率
public static int calculateInSampleSize(
BitmapFactory.Options options, int reqWidth, int reqHeight) {
// 位图的原宽高通过options对象获取
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
//当要显示的目标大小和图像的实际大小比较接近时,会产生没必要的采样,先除以2再判断以防止过度采样
while ((halfHeight / inSampleSize) >= reqHeight
&& (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
return inSampleSize;
}