Bitmap学习笔记

本文主要讲述Bitmap一些概念常用方法,用它可以获取图像文件信息,进行图像剪切、旋转、缩放和镜像操作,并可以指定格式保存图像文件,并且简单介绍一下与Drawabled区别,用这些常用的方法来完成一些特定的效果,比如刮刮卡或者图片圆角功能,当然了撕衣服这个(gao)色(da)色(shang)的demo也是所介绍的功能之一。

tear

概要

位图图像(bitmap), 亦称为点阵图像或绘制图像,是由称作像素(图片元素)的单个点组成的。因此一般而言同样大小的图片如果采用位图存储,它要比jpg或png稍大,因为bmp格式文件是没有被压缩过的,而jpg和png都采用了压缩算法对图片进行了优化处理。既然bmp格式图片没有被压缩处理,但是它却是Android手机中最常用的一种图片处理格式,可以这么理解不要你的原因有千百种,然而需要你的原因只有一个,只要这个原因存在其它的就都不重要了,这个原因就是Bitmap可以进行像素级别的图片处理。

进行移动开发的人都知道,就是一般从网络获取的图片都要经过压缩处理,这样才不容易发生OOM,一般压缩图片都是尺寸方面的大小,其实除了尺寸之外,影响一个图片占用空间的还有其色彩细节。

Bitmap图片压缩质量参数Config

系统为我们提供了四种压缩质量参数,分别是ALPHA_8, ARGB_4444,ARGB_8888,RGB_565,我们知道ARGB指的是一种色彩模式,里面A代表Alpha,R表示red,G表示green,B表示blue,其实所有的可见色都是右红绿蓝组成的,所以红绿蓝又称为三原色,每个原色都存储着所表示颜色的信息值。

  • ALPHA_8就是Alpha由8位组成,此时图片只有alpha值,没有RGB值,一个像素占用一个字节,这种格式的图片,看起来质量太差,已经不推荐使用;
  • ARGB_4444就是由4个4位组成即16位,一个像素占用2个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占4个bites,共16bites,即2个字节;
  • ARGB_8888就是由4个8位组成即32位,一个像素占用4个字节,alpha(A)值,Red(R)值,Green(G)值,Blue(B)值各占8个bites,共32bites,即4个字节,这是一种高质量的图片格式,它也是Android手机上一个Bitmap的默认格式。
  • RGB_565就是R为5位,G为6位,B为5位共16位, 一个像素占用2个字节,没有alpha(A)值,即不支持透明和半透明,Red(R)值占5个bites ,Green(G)值占6个bites ,Blue(B)值占5个bites,共16bites,即2个字节。从Android4.0开始,该选项无效。即使设置为该值,系统任然会采用 ARGB_8888来构造图片

用一个简单的例子说明一下这四个参数对于存储图片大小的影响,一张1024*896大小的图片,分别计算一下各自的大小如下:

  • ALPHA_8:1024*896=896kb
  • ARGB_4444:1024*896*2=1.75M
  • ARGB_8888:1024*896*4=3.5M
  • RGB_565:1024*896*2=1.75M
    • PorterDuffXfermode简单介绍

      PorterDuffXfermode是一个非常强大的转换模式,使用它,可以使用图像合成的16条Porter-Duff规则的任意一条来控制Paint如何与已有的Canvas图像进行交互

      PorterDuffXfermode

      • PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。
      • PorterDuff.Mode.SRC显示上层绘制图片
      • PorterDuff.Mode.DST显示下层绘制图片
      • PorterDuff.Mode.SRC_OVER正常绘制显示,上下层绘制叠盖。
      • PorterDuff.Mode.DST_OVER上下层都显示。下层居上显示。
      • PorterDuff.Mode.SRC_IN取两层绘制交集。显示上层。
      • PorterDuff.Mode.DST_IN取两层绘制交集。显示下层。
      • PorterDuff.Mode.SRC_OUT取上层绘制非交集部分。
      • PorterDuff.Mode.DST_OUT取下层绘制非交集部分。
      • PorterDuff.Mode.SRC_ATOP取下层非交集部分与上层交集部分
      • PorterDuff.Mode.DST_ATOP取上层非交集部分与下层交集部分
      • PorterDuff.Mode.XOR异或:去除两图层交集部分
      • PorterDuff.Mode.DARKEN取两图层全部区域,交集部分颜色加深
      • PorterDuff.Mode.LIGHTEN取两图层全部,点亮交集部分颜色
      • PorterDuff.Mode.MULTIPLY取两图层交集部分叠加后颜色
      • PorterDuff.Mode.SCREEN取两图层全部区域,交集部分变为透明色

      Bitmap与Drawable

      Drawable转换为Bitmap

      Bitmap转换为Drawable

      Bitmap与Drawable对比

      对比项 显示清晰度 占用内存 缩放旋转平移 色相色差调整 支持透明色 绘制速度 支持像素操作
      Bitmap 相同
      Drawable 相同

      从资源文件获取Bitmap的方式

      方式一BitmapDrawable

      方式二BitmapFactory

      Bitmap创建缩略图

      创建缩略图跟图像缩放是两码事,图像缩放但是占用内存大小不变,创建缩略途之后图片实际大小为改变,占用内存也会随之改变

      方式一采用BitmapFactory

      BitmapFactory.Options 用于指定解码时的一些设置:

      • inBitmap如果设置,当加载内容时该方法将尝试重用这个位图;
      • inDensity使用像素密度来表示位图;
      • inDither如果存在抖动,解码器将尝试解码图像抖动;
      • inPurgeable如果设置为true,则由此产生的位图将分配其像素,以便系统需要回收内存时可以将它们清除;
      • inInputShareable与inPurgeable一起使用,如果inPurgeable为false那该设置将被忽略,如果为true,那么它可以决定位图是否能够共享一个指向数据源的引用,或者是进行一份拷贝;
      • inJustDecodeBounds如果设置,那返回的位图将为空,但会保存数据源图像的宽度和高度;
      • inMutable如果设置,解码方法将始终返回一个可变的位图;
      • inPreferQualityOverSpeed如果设置为true,解码器将尝试重建图像以获得更高质量的解码,甚至牺牲解码速度;
      • inPreferredConfig 如果为非空,解码器将尝试解码成这个内部配置;
      • inSampleSize 如果设置的值大于1,解码器将等比缩放图像以节约内存;
      • inScaled如果设置,当inDensity和inTargetDensity不为0,加载时该位图将被缩放,以匹配inTargetDensity,而不是依靠图形系统缩放每次将它绘制到画布上;
      • inScreenDensity当前正在使用的实际屏幕的像素密度;
      • inTargetDensity这个位图将被画到的目标的像素密度;
      • mCancel用于指示已经调用了这个对象的取消方法的标志;
      • outHeight、outWidth图像的高度和宽度;
      • outMimeType 如果知道,这个字符串将被设置为解码图像的MIME类型。

      calculateInSampleSize该方法是xUtils使用的方式,在网上的一些论坛中还有另外一种实现方式:

      这中处理方式是创建宽高不大于缩略图宽高,xUtils方式是以宽高比值中较小的一个来循环处理的,有可能所创建的缩略图会大于目标缩略图,但是即使大于也不能大于目标缩略图大小的2倍,它的这种方式可能是为了更高质量的显示效果吧。

      方式二采用ThumbnailUtils

      ThumbnailUtils在Android 2.2新增的用来实现缩略图的工具类,此工具类的功能是强大,使用是简单,它提供了一个常量和三个方法。利用这些常数和方法,可以轻松快捷的实现图片和视频的缩略图功能。

      Bitmap createVideoThumbnail(String filePath, int kind)

      Bitmap extractThumbnail(Bitmap source, int width, int height, int options)

      Bitmap extractThumbnail(Bitmap source, int width, int height)

      创建所需尺寸居中缩放的位图。

      Bitmap双缓冲技术

      这种方式是在一本Android开发的指导书上看到的,双缓冲的核心技术就是先通过setBitmap方法或者构造函数Canvas(Bitmap bitmap)将要绘制的所有的图形会知道一个Bitmap上,然后再来调用drawBitmap方法绘制出这个Bitmap,显示在屏幕上。

      Bitmap裁剪、旋转、镜像缩放

      Bitmap图像裁剪

      Bitmap createBitmap(Bitmap source, int x, int y, int width, int height)

      该方法是以图像源文件source左上角为坐标原点,以(X,Y)为起点,分别以width和height进行裁剪。

      图像缩放

      在系统中有三种方式可以对Bitmap源文件进行缩放

      1. 采用矩阵Matrix中的方法,然后在绘制时调用Canvas的drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)
      2. 调用Canvas的drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint)绘制dst大小的图像,dst是所要绘制的矩形区域大小
      3. 调用Bitmap的Bitmap createScaledBitmap(Bitmap src, int dstWidth,int dstHeight, boolean filter)方法创建指定宽(dstWidth)高(dstHeight)的位图,然后在绘制在Canvas上面

      图像的平移和旋转

      事实上都是调用的Matrix中的setRotate(float degrees)或者setRotate(float degrees, float px, float py)setTranslate(float dx, float dy)方法进行矩阵的旋转和平移

      图像镜像

      这里提供一个简单的镜像demo,是以x轴进行的镜像(对称变换)

      示例部分源代码

      撕衣服就是将手势划过的地方的像素设置为空或者使用PorterDuffXfermode方式对图像进行转换

      setPixel(int x, int y, int color)

      PorterDuffXfermode这种方式是比较推荐的方式

      刮刮卡采用同样的原理,只是后面背景图片换成了文字绘制上去,更多的代码可以参考源代码,有一个很高大上的技巧在刮刮卡的实现上,就是如果想要擦除上面涂层达到一定百分比时就自动全部清除上涂层,代码如下:

      guaguaka

      其它

      Bitmap图片有时候会需要保存图片到SDcard,事实上调用Bitmap的compress(CompressFormat format, int quality, OutputStream stream)方法就可以了,但是这时候在图库中并不会实时显示我们已经保存的图片,需要发送一个系统通知来让系统扫描一下文件系统:

      本文地址www.sunnyang.com/284.html

      示例源代码下载

One comment

发表评论