• Android笔记--Bitmap


    Android | Bitmap解析

    Android中Bitmap是对图像的一种抽象。通过他可以对相应的图像进行剪裁,旋转,压缩,缩放等操作。这里循序渐进的一步步了解Bitmap的相关内容。
    先了解Bitmap相关的API,然后根据API进一步了解内部的实现。


    1.生成Bitmap--BitmapFactory

    android.graphics.Bitmap.java

     /**
     * Private constructor that must received an already allocated native bitmap
     * int (pointer).
     */
    // called from JNI Bitmap类中只有一个构造器。而且还不能直接调,必须通过JNI去构造
    Bitmap(long nativeBitmap, byte[] buffer, int width, int height, int density,
            boolean isMutable, boolean requestPremultiplied,
            byte[] ninePatchChunk, NinePatch.InsetStruct ninePatchInsets) {
    	...
    }
    

    Bitmap类中只有一个构造器。而且还不能直接调,必须通过JNI去构造。源码中已经写的很清楚。所以一定有JNI的方式产生Bitmap对象。这就是BitmapFactory的功能--生成Bitmap

    android.graphics.BitmapFactory.java

    	/**
    * Creates Bitmap objects from various sources, including files, streams,
    * and byte-arrays.
     */
    public class BitmapFactory {
    	...
    }
    

    通过这个类可以看到所有的方法都是静态方法。而且支持从文件,流,字节数组等各种资源中获取Bitmap对象。

    从结构图可以看出生成Bitmap的方式有四大类:
    decodeFile 从文件系统加载
    decodeResource 以R.drawable.xxx的形式从本地资源中加载
    decodeStream 从输入流加载
    decodeByteArray 从字节数组中加载

    其中decodeFile和decodeResource间接调用decodeStream方法。而且返回Bitmap使用前要判空,在不存在的情况下会返回null.

    每一种decodeXXX方法最后都有一个Options对象。这个对象的作用就是在decode解压到内存之前的一些可选项。利用这些可选项可以优化内存,以及展示的效果等。

    Options是BitmapFactory的静态内部类

    常用的配置有:

    inPreferredConfig | 指定位图编码格式 可选项在Bitmap.Config中,缺省值是ARGB_8888。

    inJustDecodeBounds | true 返回的Bitmap将是null,但是Options的outAbc中解出了图像的基本信息

    inSampleSize | 采样率,设置缩放比例.采样率就是抽取像素点组成位图,采样率同时作用于宽和高。

    比如inSampleSize为2,采样后的图片的宽高均为原始图片宽高的1/2,这时像素=原始图片的1/4,占用内存=原始图片的1/4;

    inSampleSize的取值应该总为2的整数倍,否则会向下取整,取一个最接近2的整数倍,比如inSampleSize=3时,系统会取inSampleSize=2
    假设一张10241024,模式为ARGB_8888的图片,inSampleSize=2,原始占用内存大小是4MB,采样后的图片占用内存大小就是(1024/2) * (1024/2 ) 4 = 1MB

    备注:

    ALPHA_8:每个像素占用1byte内存。
    ARGB_4444:每个像素占用2byte内存
    ARGB_8888:每个像素占用4byte内存(默认为改格式)
    RGB_565:每个像素占用2byte内存

    所以默认一张1024*1024像素的位图是4MB的,如果硬生生加载进内存会占用很大一块。很容易造成OOM!因此就需要Options去提前配置一下。


    2.Bitmap方法对自身的变换

    Bitmap可以和Matrix结合实现图像的剪切、旋转、缩放等操作,最终调用到的createXXXBitmapXXX方法有下面几个:

    他们最终都会调用native方法:

    //////////// native methods
    
    private static native Bitmap nativeCreate(int[] colors, int offset,
                                              int stride, int width, int height,
                                              int nativeConfig, boolean mutable);
    

    可见他们的变换本质都是一样的。只是调用的方式不同

    用源Bitmap通过变换生成新的Bitmap的方法:

    public static Bitmap createBitmap(Bitmap source, int x, int y, intwidth, int height,  
                Matrix m, boolean filter) //最终的实现,后两种只是对第一种方法的封 ,
    //设置Matrix的Rotate(通过setRotate())或者Scale(通过setScale()),传入第一个方法,可实现旋转或缩放。
    
    public static Bitmap createBitmap(Bitmap source, int x, int y, intwidth, int height)
    //可以从源Bitmap中指定区域(x,y, width, height)中挖出一块来实现剪切  
    
    public static Bitmap createScaledBitmap(Bitmap src, int dstWidth,  
                int dstHeight,boolean filter)  
    //可以把源Bitmap缩放为dstWidth x dstHeight的Bitmap
    

    用于压缩到流的方法:

    public boolean compress(CompressFormat format, int quality, OutputStream stream)
    //format指定压缩的格式:
    	一共三种
    	JPEG    (0),
        PNG     (1),
        WEBP    (2);
    //quality指定压缩品质0-100可输入。0是最差,100是无损。PNG格式压缩会忽略这个选项
    //stream 压缩输出的流在这里取出,接下去可以对流进行操作
    
    public Bitmap copy(Config config, boolean isMutable)
    //这个方法主要用于复制出一个全新的位图。Config指定新位图格式ALPHA_8, RGB_565, ARGB_4444, ARGB_8888,
    //isMutable, true表示产生的位图无法更改
    

    3.使用Bitmap需要注意的问题

    1.最常见的问题OOM

    及时释放内存

    if (!bmp.isRecycle()) {
    	bmp.recycle();   //回收图片所占的内存
    	bitmap = null;
    	system.gc();  //提醒系统及时回收	
    }
    

    recycle()并不保证立即释放占用的内存,但是可以加速内存的释放。
    释放内存以后,就不能再使用该Bitmap对象了,否则会抛异常。所以一定要保证不再使用再释放。比如,如果是在某个Activity中使用Bitmap,建议在Activity的onStop()或者onDestroy()中进行回收。

    内存中混存通用Bitmap避免多次加载。
    比如默认图片可以只加载一次然后一个界面内多处使用。

    2.图片压缩

    inSampleSize压缩是尺寸压缩,compress方法是质量压缩。

    compress方法在保持像素的前提下改变图片的位深及透明度等,来达到压缩图片的目的,经过它压缩的图片文件存储大小会改变,但导入成bitmap后占内存大小不变,宽高也不会改变。

  • 相关阅读:
    java数组转list
    【转载】tomcat端口被占用问题完美解决方案!
    基于apicloud的英语课堂app设计与实现
    springboot整合mybatis(SSM开发环境搭建)
    POI Excel读取图片对应位置和顺序生成图片方法
    E: Sub-process /usr/bin/dpkg returned an error code (1) 出错解决方案
    Ubuntu 虚拟机无法关机的解决方案
    Celery 提示[ERROR/MainProcess] consumer: Cannot connect to amqp://guest:**@127.0.0.1:5672//: [Errno 61] Connection refused.
    Python @classmethod&@staticmethod 区别
    SyntaxError: non-default argument follows default argument
  • 原文地址:https://www.cnblogs.com/zharma/p/8330029.html
Copyright © 2020-2023  润新知