第7章 Android图形与图像处理

本章主要介绍了Android的图形、图像处理,按照下面思维导图的思路来梳理本章书的内容。重点学习使用简单图片方法;Android丰富的绘图API,包括Canvas、Paint、Path等类;各种图形特效,利用Matrix对图形进行几何变换;最后是Android的动画支持。

【知识点】
· Bitmap和BitmapFactory
     Bitmap代表一张位图,BitmapDrawable里封装的图片就是一个Bitmap对象。开发者为了把一个Bitmap对象包装成BitmapDrawable对象,可调用BitmapDrawable构造器:
// 把一个Bitmap对象包装成BitmapDrawable对象
BitmapDrawable drawable  =  new BitmapDrawable(bitmap);
如果需要获取BitmapDrawable所包装的Bitmap对象,则可以调用BitmapDrawable的getBitmap()方法,如下面的代码所示:
  //获取一个BitmapDrawable所包装的Bitmap对象
Bitmap bitmap =drawable.getBitmap();

     BitmapFactory是一个工具类,它用于提供大量的方法,这些方法可用于从不同的数据源来解析、创建Bitmap对象,BitmapFactory包含如下方法:

    手机系统的内存比较小,如果系统不停地去解析、创建Bitmap对象,可能由于前面创建Bitmap所占用的内存还没有回收,从而导致程序运行时引发OutOfMemory错误。Android为Bitmap提供了两个方法来判断它是否已回收,以及强制Bitmap回收自己:
    boolean isRecycled():返回该Bitmap是否已被回收。
      void recycle():强制一个Bitmap对象立即回收自己。
除此之外,如果Android应用需要访问其它存储路径(比如SD卡中)里的图片,都需要借助于BitmapFactory来解析、创建Bitmap对象。

·绘图:
    Android的绘图应该继承View组件,并重写它的onDraw(Canvas canvas)方法即可。重写onDraw(Canvas canvas)方法时涉及一个绘图APICanvas,Canvas代表了“依附”于指定View的画布,它提供了一些方法绘制各种图形。
Canvas还提供了如下方法进行变换:

    Canvas提供的上面的方法还涉及一个API:Paint,Paint代表了Canvas上的画笔,因此Paint类主要用于设置绘制风格,包括画笔颜色、画笔笔触粗细、填充风格等。
    在Canvas提供的绘制方法中还用到了一个API:Path,Path代表任意多条直线连接而成的任意图形,当Canvas根据Path绘制时,它可以绘制出任意的形状。

·使用 Matrix控制图像或组件变换步骤:
①获取 Matrix对象,该 Matrix对象既可创建,也可直接获取其他对象内封装的 Matrix;
②调用 Matrix的方法进行平移、旋转、缩放、倾斜等;
③将程序对 Matrix所做的变换应用到指定图像或组件。


·双缓冲机制
    每次View组件上的图形状态数据发生了改变,都应该通知View组件重写onDraw(Canvas canvas)方法重绘组件。通知View重绘可调用invalidate(在UI线程中)或postInvalidate(非UI线程中)。 当程序需要在指定View上进行绘制时,程序并不直接绘制到View组件上,而是先绘制到一个内存中的Bitmap图片(这就是缓冲)上,等到内存中的Bitmap绘制好之后,再一次性地将Bitmap绘制到View组件上。

· 逐帧动画
    逐帧(Frame)是最容易理解的动画,它要求开发者把动画过程的每张静态图片都收集起来,然后由Android来控制依次显示这些静态图片。 逐帧动画通常也是采用XML资源文件进行定义的。定义逐帧动画非常简单,只要在<animation-list.../>元素中使用<item.../>子元素定义动画的全部帧,并指定各帧的持续时间即可。
    一旦程序获取了AnimationDrawable对象之后,接下来接可用ImageView把AnimationDrawable显示出来----习惯上把AnimationDrawable设成ImageView的背景即可。 需要指出的是:AnimationDrawable代表的动画默认是不播放的,必须在程序中启动动画播放才可以。AnimationDrawable提供了入戏两个方法来开始、停止动画:
    start():开始播放动画
      stop():停止播放动画

· 补间(Tween)动画
    补间动画就是指开发者只需要指定动画开始、动画结束“关键帧”,而动画变化的“中间帧”由系统计算并补齐。 对于补间动画而言,开发者无需“逐一”定义动画过程中的每一帧,他只要定义动画开始、结束的关键帧,并指定动画的持续时间即可。 补间动画所定义的开始帧、结束帧其实只是一些简单的变化,比如图形大小的缩放、旋转角度的改变等,Android使用Animation代表抽象的动画类,它包括如下几个子类:
     AlphaAnimation:透明度改变的动画,其中透明度可从0变化到1。创建时指定开始透明度、结束透明度和持续时间。
     ScaleAnimation:大小缩放的动画。创建时指定开始缩放比、结束缩放比、持续时间,还要指定“缩放中心”坐标。
     TranslateAnimation:位移变化的动画,只要设置开始位置、结束位置和持续时间即可。
     RotateAnimation:旋转动画。创建时指定动画开始旋转角度、结束旋转角度、持续时间,还要指定“旋转中心”坐标。
 
    一旦为补间动画指定了3个必要信息,Android就会根据动画的开始帧、结束帧、动画持续时间计算出需要在中间“补入”多少帧,并计算所有补入帧的图形。当用户浏览补间动画时,他眼中看到的依然是“逐帧动画”。
     为了控制在动画期间需要“补入”多少帧,具体在动画运行的哪些时刻补入帧,需要借助于Interpolator。 Interpolator根据特定的算法计算出整个动画所需要动态插入帧的密度和位置。简单的说就是Interpolator负责控制动画的变化速度,这就使得基本的动画效果(Alpha、Scale、Translate、Rotate)能以匀速、加速、减速、抛物线速度等各种速度变化。
    Android为Interpolator提供了如下几个实现类,分别用于实现不同动画变化速度:  
          LinearInterpolator:动画以均匀的速度变化。
          AccelerateInterpolator:在动画开始的地方改变速度较慢,然后开始加速。
          AccelerateDecelerateInterpolator:在动画开始、结束的地方改变速度较慢,在中间的时候加速。
          CycleInterpolator:动画循环播放特定的次数,变化速度按正弦曲线变化。
          DecelerateInterpolator:在动画开始的地方改变速度较快,然后开始减速。
     为了在动画资源文件中指定补间动画所使用的Interpolator,定义补间动画的<set.../>元素支持一个android:interpolator属性,该属性可指定默认的Interpolator。例如:
@android:anim/linear_interpolator
@android:anim/accelerate_interpolator
@android:anim/accelerate_decelerate_interpolator
    一旦在程序中通过AnimationUtils得到代表补间动画的Animation之后,接下来就可以调用View的startAnimation(Animation anim)方法开始对View执行动画了。

· 属性动画
    属性动画需要定义如下几方面的属性:
         动画持续时间,通过android:duration属性指定。
         动画差值方式,通过android:interpolator属性指定。
         动画重复次数,通过android:repeatCount属性指定。
         重复行为,通过 android:repeatMode 属性指定。
         动画集,在属性动画资源文件中通过<set.../>元素来组合,该元素的 android:ordering 属性指定该组动画是按次序播放,还是同时播放。
         帧刷新频率。
    使用属性动画的步骤:
         ①创建ValueAnimator或ObjectAnimator对象
         ②根据需要为 Animator对象设置属性
         ③如果需要监听 Animator的动画开始事件、动画结束事件、动画重复事件、动画值改变事件,并根据事件提供响应处理代码,应该为 Animator对象设置事件监听器
         ④如果有多个动画需要按次序或同时播放,应使用 AnimatorSet组合这些动画
         ⑤调用 Animator对象的start()方法启动动画。

· 使用SurfaceView实现动画
    SurfaceView一般会与SurfaceHolder结合使用, SurfaceHolder用于向与之关联的SurfaceView上绘图,调用SurfaceView的getHolder()方法即可获取SurfaceView关联的 SurfaceHolder。 SurfaceHolder提供了如下方法来获取Canvas对象:
         Canvas lockCanvas():锁定整个 SurfaceView对象,获取其上的Canvas。
         Canvas lockCanvas(Rect dirty):锁定 SurfaceView上Rect划分的区域,获取其上的Canvas。
    获取指定了SurfaceView上的Canvas之后,程序就可以调用Canvas绘图,绘图完成后通过如下方法来释放绘图,提交所绘制的图形:
         unlockCanvasAndPost(canvas);
    需要指出的是,当调用SurfaceHolder的 unlockCanvasAndPost方法之后,该方法之前所绘制的图形还在缓冲中,下一次的lockCanvas()方法锁定的区域可能会“遮挡”它。

【问题】
·问:书中有处代码用到了BlurMaskFilter、EmbossMaskFilter等,问 BlurMaskFilter? EmbossMaskFilter?
  答: MaskFilter 类可以为Paint分配边缘效果。 对MaskFilter的扩展可以对一个Paint边缘的alpha通道应用转换。Android包含了下面几种MaskFilter:
          BlurMaskFilter   指定了一个模糊的样式和半径来处理Paint的边缘,实现喷涂效果,构造方法如下:
    public  BlurMaskFilter(float radius,  BlurMaskFilter.Blur style )
其中,Radius:喷涂半径,Style:喷涂类型。    
          EmbossMaskFilter  指定了光源的方向和环境光强度来添加浮雕效果。构造方法如下:
     public  EmbossMaskFilter(float[] direction,float ambient,float specular,float blurRadius)
其中,direction:表示光源从x、y、z照射曲线的方向,ambient:表示周围光源的数量,specular:表示光照的反射系数,blurRadius:在光照前喷涂的范围。
    
    要应用一个MaskFilter,可以使用setMaskFilter方法,并传递给它一个MaskFilter对象。下面的例子是对一个已经存在的Paint应用一个EmbossMaskFilter:
 // 设置光源的方向    
 float[] direction = new float[]{ 1, 1, 1 };    
 //设置环境光亮度    
 float light = 0.4f;    
 // 选择要应用的反射等级    
 float specular = 6;    
 // 向mask应用一定级别的模糊    
 float blur = 3.5f;    
 EmbossMaskFilter emboss=new EmbossMaskFilter(direction,light,specular,blur);    
    
 // 应用mask    
myPaint.setMaskFilter(emboss);   
来源: <http://yueguc.iteye.com/blog/782525#>


SDK中包含的FingerPaint API demo是说明如何使用MaskFilter的一个非常好的例子。它展示了这两种filter的效果。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值