安卓之Bitmap

一、基本介绍

Bitmap(位图)。本质上就是一张图片的内容在内存中的表达形式。
Bitmap原理:从纯数学的角度,任何一个面都由无数个点组成。但是对于图片而言,我们没必要用无数个点来表示这个图片,只需要将一张图片表示为有限但足够多的点即可。点的数量不能无限,因为无限的点信息量太大无法存储;但是点的数量也必须足够多,否则视觉上无法形成连贯性。这里的点就是像素。比如说,某个1080*640的图片,这里的像素总数即为1080X640个。Bitmap就是封装了这些像素点的对象。
像素信息:每个像素的信息,就是ARGB四个通道的值。其中,A代表透明度,RGB代表红绿蓝三种颜色通道值。每个通道的值范围在0~255之间,即有256个值,刚好可以通过一个字节(8bit)进行表示。
这里有两个现实的需求问题:
①在实际需求中,我们真的需要这么多数量的颜色吗?上述方案是256X256X256种。有的时候,我们并不需要这么丰富的颜色数量,所以可以适当减少表示每个颜色通道的bit位数。这么做的好处是节省空间。也就是说,每个颜色通道都采用8bit来表示是代表全部颜色值的集合;而我们可以采用少于8bit的表示方式,尽管这会缺失一部分颜色值,但是只要颜色够用即可,并且这还可以节省内存空间。

②我们真的需要透明度值吗?如果我们需要某个图片作为背景或者图标,这个图片透明度A通道值是必要的。但是如果我们只是普通的图片展示,比如拍摄的照片,透明度值毫无意义。细想一下,你希望你手机自拍的照片透明或者半透明吗?hell no! 因此,透明度这个通道值是否有必要表示也是根据需求自由变化的。

二、详细介绍

1、Bitmap.Config类
这个枚举类的变量有四个值ALPHA_8,RGB_565,ARGB_4444,ARGB_8888:
对应ARGB色彩模式的四个标准。ARGB分别表示Alpha(透明度)通道,R(red红色)通道,G(Green绿色)通道,(Blue蓝色)通道。
1.ALPHA_8 没有色彩,只存储透明度A通道值,使用场景特殊,比如设置遮盖效果等
2.RGB_565 色彩不丰富,RGB通道值分别占5、6、5位,但是没有存储A通道值,所以不支持透明度。
3.ARGB_4444 早期Android使用,现已经废弃,因为在现在高分辨率手机下显示效果差
4.ARGB_8888 Android图片默认使用标准。色彩丰富,同时占用内存也大

2、Bitmap的压缩存储
Bitmap是图片内容在内存中的表示形式,那么如果想要将Bitmap对象进行持久化存储为一张本地图片,需要对Bitmap对象表示的内容进行压缩存储。根据不同的压缩算法可以得到不同的图片压缩格式,比如GIF、JPEG、BMP、PNG和WebP等。
换句话说:Bitmap是图片在内存中的表示,GIF、JPEG、BMP、PNG和WebP等格式图片是持久化存储后的图片。内存中的Bitmap到磁盘上的GIF、JPEG、BMP、PNG和WebP等格式图片经过了”压缩”过程,磁盘上的GIF、JPEG、BMP、PNG和WebP等格式图片到内存中的Bitmap经过了“解压缩”的过程。
那么,为什么不直接将Bitmap对象进行持久化存储而是要对Bitmap对象进行压缩存储呢?这么做依据的思想是:当图片持久化保存在磁盘上时,我们应该尽可能以最小的体积来保存同一张图片的内容,这样有利于节省磁盘空间;而当图片加载到内存中以显示的时候,应该将磁盘上压缩存储的图片内容完整地展开。前者即为压缩过程,目的是节省磁盘空间;后者即为解压缩过程,目的是在内存中展示图片的完整内容。

3、有损压缩和无损压缩

Bitmap压缩存储时的算法有很多种,但是整体可分为两类:有损压缩和无损压缩。

①有损压缩
有损压缩的原理是:保持颜色的逐渐变化,删除图像中颜色的突然变化。生物学中的大量实验证明,人类大脑会自发地利用与附近最接近的颜色来填补所丢失的颜色。有损压缩的具体实现方法就是删除图像中景物边缘的某些颜色部分。当在屏幕上看这幅图时,大脑会利用在景物上看到的颜色填补所丢失的颜色部分。利用有损压缩技术,某些数据被有意地删除了,并且在图片重新加载至内存中时这些数据也不会还原,因此被称为是“有损”的。有损压缩技术可以灵活地设置压缩率。例如JPG格式的图片。

②无损压缩
无损压缩的基本原理是:相同的颜色信息只需保存一次。具体过程是:首先会确定图像中哪些区域是相同的,哪些是不同的。包括了重复数据的区域就可以被压缩,只需要记录该区域的起始点即可。优点是能够比较好地保存图像的质量,但是相对来说这种方法的压缩率比较低。例如PNG格式的图片。
对比分析:有损压缩压缩率高而且可以灵活设置压缩率,并且删除的数据不可还原,因此可以减少图片的内存占用,但是对图片质量会有一定程度的影响;无损压缩可以很好地保存图片质量,也能保证一定的压缩率虽然没有有损压缩那么高,并且无损压缩删除的数据在重新加载至内存时会被还原,因此不可以减少图片的内存占用。

三、基本使用

Bitmap常用API:

public void recycle()  // 回收位图占用的内存空间,把位图标记为Dead
public final boolean isRecycled()  //判断位图内存是否已释放
public final int getWidth() //获取位图的宽度
public final int getHeight() //获取位图的高度
public final boolean isMutable() //图片是否可修改
public int getScaledWidth(Canvas canvas) //获取指定密度转换后的图像的宽度
public int getScaledHeight(Canvas canvas) //获取指定密度转换后的图像的高度
public static Bitmap createBitmap(Bitmap src)  //以src为原图生成不可变得新图像
public static Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) //以src为原图,创建新的图像,指定新图像的高宽以及是否可变。
public static Bitmap createBitmap(int width, int height, Config config) //创建指定格式、大小的位图
public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height) //以source为原图,创建新的图片,指定起始坐标以及新图像的高宽。
public boolean compress(CompressFormat format, int quality, OutputStream stream) //按指定的图片格式以及画质,将图片转换为输出流。
/**
format:压缩图像的格式,如Bitmap.CompressFormat.PNG或+ Bitmap.CompressFormat.JPEG
quality:画质,0-100.0表示最低画质压缩,100以最高画质压缩。对于PNG等无损格式的图片,会忽略此项设置。
stream: OutputStream中写入压缩数据。
return: 是否成功压缩到指定的流。
*/

BitmapFactory
用于从不同的数据源(如文件、输入流、资源文件、字节数组、文件描述符等)解析、创建Bitmap对象
部分方法

public static Bitmap decodeFile(String pathName, Options opts)  //从文件读取图片
public static Bitmap decodeFile(String pathName)
public static Bitmap decodeStream(InputStream is)  //从输入流读取图片
public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts)
public static Bitmap decodeResource(Resources res, int id)  //从资源文件读取图片
public static Bitmap decodeResource(Resources res, int id, Options opts)
public static Bitmap decodeByteArray(byte[] data, int offset, int length)  //从数组读取图片

BitmapFactory.Options 类允许我们定义图片以何种方式如何读到内存。
BitmapFactory.Options 类详情请自查阅。

/**
     * 保存内存中的bitmap到本地文件
     * @param bitmap 要保存的bitmap
     * @param localPath 保存在本地的文件名,绝对路径
     * */
    public static void saveBitmap2File(Bitmap bitmap,String localPath){
        if (bitmap == null) {
            return;
        }
        try {
            File file = new File(localPath);
            FileOutputStream fos = new FileOutputStream(file);
            assert bitmap != null;
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);//100表示正常质量,如果压缩之类的更改压缩质量即可
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
/**
     * 圆片压缩
     * 
     * @param bitmap
     * @return
     */
    private Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
        return bitmap;
    }

部分来自该博主
几何变换
canvas和Matrix可对Bitmap进行旋转、放缩、平移、切错等操作
对 bitmap 进行裁剪
推荐阅读该链接内容学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值