美文网首页
初识Android Bitmap

初识Android Bitmap

作者: 狮_子歌歌 | 来源:发表于2016-10-06 17:01 被阅读1212次

    Bitmap

    Drawable,Canvas和Bitmap

    • drawable:通用的图形对象,用于装载常用格式的图像,既可以是PNG,JPG,gif这样的图像。同时包含13种Drawable类型的可视化对象,StateListDrawable,BitmapDrawable...
    • Canvas:画布,也就是我们可以绘制的区域。提供了drawXXX()等方法来便捷的绘制图形。
    • Bitmap:是一种存储像素的数据结构,通过这个对象可以得到一系列的图像属性。还可以对图像进行旋转,切割,放大,缩小等操作。

    个人理解:Bitmap是一种数据结构,存储像素信息。Drawable 储存的是 对 Canvas 的一系列操作。而 BitmapDrawable 储存的是「把 Bitmap 渲染到 Canvas 上」这个操作。

    Bitmap,BitmapFactory,BitmapFacotry.Options

    获取Bitmap

    由于Bitmap的构造方法私有化,所以我们不能在外部直接实例化一个Bitmap对象。我们只能通过BitmapFactory来得到Bitmap对象。

    BitmapFractory常用获取Bitmap的方法:

    途径 方法
    从文件中解析 decodeFile(String pathName, Options), decodeFile(String pathName)
    从res/目录下解析 decodeResource(Resources res,int id), decodeResurce(Resources res, int id, Options)
    从字节数组中解析 decodeByteArray(byte[] data, int offset, int length), decodeByteArray(byte[] data, int offset, int length, BitmapFactory.Options opts)
    从流中解析 decodeStream(InputStream is), decodeStream(InputStream is, Rect outPadding, BitmapFactory.Options opts)

    通过上述表格我们发现,无论是哪一种途径得到的Bitmap都有一种重载方法的参数列中多了一个BitmapFacotry.Options参数。那么BitmapFacotry.Options是干嘛的呢?

    举个例子,我们为了缩放图像想要获取该图像的大小,那么首先要在代码中获取这个图像的Bitmap对象,然后通过Bitmap.getWidth()和getheight()方法来获取图像的大小。但是如果想要获取一个大图像的大小,在得到Bitmap对象时会造成oom。这时我们就可以用到BitmapFractory.Options对象的inJustDecodeBounds字段。操作方法:

    • 首先获取一个Options对象,并将inJustDecodeBounds设置为True。
    • 然后选择一种获取Bitmap途径的方法,并传入Options对象。此时该方法返回的Bitmap为null。
    • 然后通过Options.outWidth和outHeight来获取院士图片的大小
    • 通过设置Options.inSampleSize来决定获取Bitmap时缩小图像长宽的系数。
    • 最后我们把Options实例的inJustDecodeBounds设置为false,并通过该实例获取大图像的Bitmap。这样就防止了OOM

    BitmapFactory.Options类有一个参数inSampleSize,该参数为int型,他的值指示了在解析图片为Bitmap时在长宽两个方向上像素缩小的倍数。inSampleSize的默认值和最小值为1(当小于1时,解码器将该值当做1来处理),且在大于1时,该值只能为2的幂(当不为2的幂时,解码器会取与该值最接近的2的幂)。参考博文高效使用Bitmaps(一) 大Bitmap的加载,BitmapFactory.Options详解

    Bitmap常用方法

    • public boolean compress (Bitmap.CompressFormat format, int quality, OutputStream stream) 将位图的压缩到指定的OutputStream,可以理解成将Bitmap保存到文件中!
      • format:格式,PNG,JPG等;
      • quality:压缩质量,0-100,0表示最低画质压缩,100最大质量(PNG无损,会忽略品质设定)
      • stream:输出流
      • 返回值代表是否成功压缩到指定流!
    • void recycle():回收位图占用的内存空间,把位图标记为Dead
    • boolean isRecycled():判断位图内存是否已释放
    • int getWidth():获取位图的宽度
    • int getHeight():获取位图的高度
    • boolean isMutable():图片是否可修改
    • int getScaledWidth(Canvas canvas):获取指定密度转换后的图像的宽度
    • int getScaledHeight(Canvas canvas):获取指定密度转换后的图像的高度
    • Bitmap createBitmap(Bitmap src):以src为原图生成不可变得新图像
    • Bitmap createScaledBitmap(Bitmap src, int dstWidth,int dstHeight, boolean filter):以src为原图,创建新的图像,指定新图像的高宽以及是否变。
    • Bitmap createBitmap(int width, int height, Config config):创建指定格式、大小的位图
    • Bitmap createBitmap(Bitmap source, int x, int y, int width, int
      height)以source为原图,创建新的图片,指定起始坐标以及新图像的高宽。
    • public static Bitmap createBitmap(Bitmap source, int x, int y, int width, int height,
      Matrix m, boolean filter)

    BitmapFractory.Options字段

    • boolean inJustDecodeBounds——如果设置为true,不获取图片,不分配内存,但会返回图片的高宽度信息。
    • int inSampleSize——图片缩放的倍数。如果设为4,则宽和高都为原来的1/4,则图是原来的1/16。
    • int outWidth——获取图片的宽度值
    • int outHeight——获取图片的高度值
    • int inDensity——用于位图的像素压缩比
    • int inTargetDensity——用于目标位图的像素压缩比(要生成的位图)
    • boolean inScaled——设置为true时进行图片压缩,从inDensity到inTargetDensity。

    获取Bitmap实例

    从资源中获取位图的方式有两种:通过BitmapDrawable或者BitmapFactory。

    BitmapDrawable

    Android支持三种格式的位图图像:.png (preferred),.jpg (acceptable), .gif (discouraged)。
    括号里的说明,代表这三种格式的图片在Android中的支持情况,.png格式图片优先,.jpg格式也可以,但是效果没有.png好,.gif支持最差。

    在构建应用的时候,Bitmap文件可能会被appt工具压缩自动优化为无损图像。例如,一个真彩色PNG,不需要超过256的颜色可以被转换成一个8位PNG和调色板。这将导致一个图像质量相同,但这需要更少的内存。所以要意识到,在drawable目录中图像的二进制文件在构建程序时可以改变。如果你打算读一个图像作为字节流并将它转换成一个位图,把你的图片放在在res /raw/文件夹里,在那里他们不会被优化。参考博文Android Drawable Resource学习(二)、BitmapDrawable和Bitmap

    获取BitmapDrawable

    • Bitmap file
      我们可以直接从res/drawable目录下的图片文件(.jpg,.png,.gif)获取drawable对象,并将其转型为BitmapDrawable

    res/drawable目录下的图片文件(.jpg,.png,.gif)编译资源数据类型:指向BitmapDrawable类型的指针。

    • XML Bitmap:
      一个XML bitmap是一个在XML文件中定义的指向一个bitmap文件的资源。其效果是作为一个原始位图文件的别名,并且可以指定一些额外的属性。<bitmap>是Bitmap XML的根标签,它有很多属性设置,实现平铺、拉伸或保持图片原始大小,也可以指定对齐方式等效果。可以参考博文Android样式的开发:drawable汇总篇

    同样编译资源类型指向BitmapDrawable类型的指针

    Drawable向下转型

    Resources res=getResources();  
    Drawable drawable = res.getDrawable(R.drawable.file_name);  
    //实际上这是一个BitmapDrawable对象  
    BitmapDrawable bitmapDrawable=(BitmapDrawable)drawable;  
    //可以在调用getBitmap方法,得到这个位图  
    Bitmap bitmap=bitmapDrawable.getBitmap(); 
    

    BitmapDrawable构造方法

    InputStream is=res.openRawResource(R.drawable.file_name);
    BitmapDrawable bmpDraw=new BitmapDrawable(is);
    Bitmap bmp=bmpDraw.getBitmap();
    

    还有其他构造方法,可以查阅官方文档

    Bitmap 2 BitmapDrawable

    Drawable drawable = new BitmapDrawable(bitmap);
    

    BitmapFactory

    通过上述表格中各种途径的静态方法来获取Bitmap

    //res/drawable目录下资源id获取
    BitmapFactory.decodeResource(res, resId);
    //文件路径获取
    BitmapFactory.decodeFile(pathName);
    //输入流获取
    BitmapFactory.decodeStream(inputStream);
    

    字节流

    从字节流获取Bitmap

    public Bitmap Bytes2Bimap(byte[] b) {  
        if (b.length != 0) {  
            return BitmapFactory.decodeByteArray(b, 0, b.length);  
        } else {  
            return null;  
        }  
    } 
    

    Bitmap转换为字节流

    public byte[] Bitmap2Bytes(Bitmap bm) {  
        ByteArrayOutputStream baos = new ByteArrayOutputStream();  
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);  
        return baos.toByteArray();  
    }  
    

    Bitmap.Config

    在Bitmap类里createBitmap(intwidth, int height, Bitmap.Config config)方法里有一个参数Bitmap.Config是用来做什么的呢?

    要解决Bitmap的OOM问题可以有两种方法:

    • 压缩大图片的大小,缩放
    • 改变大图片的色彩存储方法

    那么Bitmap.Config就是图片存储颜色。在Bitmap.Config文档中我们看到四个枚举变量。

    • Bitmap.Config : ALPHA_8, 就是Alpha由8位组成
    • Bitmap.Config : ARGB_4444, 就是由4个4位组成即16位,
    • Bitmap.Config : ARGB_8888, 就是由4个8位组成即32位,
    • Bitmap.Config : RGB_565, 就是R为5位,G为6位,B为5位共16位

    ARGB指的是一种色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue,其实所有的可见色都是右红绿蓝组成的,所以红绿蓝又称为三原色,每个原色都存储着所表示颜色的信息值。位图位数越高代表其可以存储的颜色信息越多,当然图像也就越逼真。

    参考博文android图片压缩质量参数Bitmap.Config RGB_565等的含义

    Bitmap缩放

    public static Bitmap getScaledBitmap(String path, int destWidth, int destHeight) {
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeFile(path, options);
    
            float srcWidth = options.outWidth;
            float srcHeight = options.outHeight;
    
            int inSampleSize = 1;
            if(srcHeight > destHeight || srcWidth > destWidth) {
                if(srcWidth > srcHeight) {
                    inSampleSize = Math.round(srcHeight / destHeight);
                } else {
                    inSampleSize = Math.round(srcWidth /destWidth);
                }
            }
    
            options = new BitmapFactory.Options();
            options.inSampleSize = inSampleSize;
    
            return BitmapFactory.decodeFile(path, options);
        }
    

    参考

    android图片压缩质量参数Bitmap.Config RGB_565等的含义

    Android基础入门教程——8.2.1 Bitmap(位图)详解

    高效使用Bitmaps(一) 大Bitmap的加载,BitmapFactory.Options详解

    Android样式的开发:drawable汇总篇

    【Android】Drawable、Bitmap、Canvas、Paint之间区别

    目标

    • 图片的两种解决OOM问题

    相关文章

      网友评论

          本文标题:初识Android Bitmap

          本文链接:https://www.haomeiwen.com/subject/xsweyttx.html