zoukankan      html  css  js  c++  java
  • 设定画笔风格实现不同的图片效果

          在上一篇文章中,学习了通过设置矩阵来达到图片变形的效果。没读过的朋友可以点击下面的链接:

    http://www.cnblogs.com/fuly550871915/p/4886353.html

          在这一篇文章中,快马加鞭,继续学习图片变形的方法。通过给画笔设定xFermode风格,可以达到很多常见的图像效果。那么首先先来简单了解一下xFermode风格。

    一、基础知识

          配合下面的一张图,来说一说什么是xFermode风格。如下:

     

          正如图中所示,列举了一些xfermode风格。比如Clear就是一个空白风格,此时画笔移动将会画空白,相当于一个橡皮擦的效果。再比如Srcin风格,你可以把它想象成两张图叠加(图中的圆和方块),求出它们交集里位于下面的图片(即最后显示的是方块的颜色)。同理,DstIn就是求交集后位于上面的图片。xfermode风格有很多很多种,这里不一一解释了,用到的时候再细细看吧。那么如何给画笔设定xfermode风格呢?利用的是一句代码,如下:

    //为画笔设置xFermode风格,只有具有alpha通道的图片才有效
    paint.setXfermode(newPorterDuffXfermode(PorterDuff.Mode.SRC_IN));

          其中paint是一只画笔。注意到注释中有一句话:只有具有alpha通道的图片才有效。为什么呢?其实翻看源码,可以发现SrcIn风格并不是像前面我们说的是图片相交求交集,只是它的效果看起来像这样子而已。其实它的真正原理是有严格的计算公式的。我截一张图如下:

          这是源码中的说明,注释中的S和D表示不同位置的图片,android中将canvas先画的图片作为Dst,将后画的图片作为Src。注释中的a就是表示透明度alpha。因为说,这种风格只有有透明度通道的图片才有效,如果一张图片没有透明度通道,那么将不可使用。

         另外需要注意的是,因为xfermode的很多特性不支持硬件加速,因为使用前,一定要禁用硬件加速,即写下下面一句代码:

    1 setLayerType(LAYER_TYPE_SOFTWARE, null);//注意,一定要禁用硬件加速器

          

           好了,你或许仍旧感到云里雾里。没关系,跟着我一起做一个实际例子,实际例子是最好的学习资料。那么我们来实现一个常见的图片效果吧。比如一张圆角的图片是如何实现的呢?如下图:

        而它的实际图片为:

        下面我们就来写实际的代码,来实现这样子的效果。

    二、实战

          在上一篇的文章中的代码基础上,继续来写今天的代码。需要一张长方形的小图片,读者可自行替换为自己的图片即可。实现上面效果的思路很简单,其实即使用canvas前后分别画一个圆角矩形和原来的图片,然后设定画笔xfermode风格来求交集即可。但是注意,要点就是先画出圆角矩形,再画出原来图片,xfermode风格设定为SrcIn。

         新建类MyXFerModeView继承自view,在这个里面,我们完成圆角矩形以及原来图片的绘制,并设定好画笔风格。如下:

     1 package com.fuly.image;
     2 
     3 import android.content.Context;
     4 import android.graphics.Bitmap;
     5 import android.graphics.BitmapFactory;
     6 import android.graphics.Canvas;
     7 import android.graphics.Paint;
     8 import android.graphics.PorterDuff;
     9 import android.graphics.PorterDuffXfermode;
    10 import android.graphics.Rect;
    11 import android.graphics.RectF;
    12 import android.graphics.Xfermode;
    13 import android.util.AttributeSet;
    14 import android.view.View;
    15 
    16 /**
    17  * 用来实验为画笔设置xFermode风格
    18  * @author fuly1314
    19  *
    20  */
    21 public class MyXFerModeView extends View{
    22     
    23     private Bitmap priBmp;
    24     private Bitmap aftBmp;
    25 
    26     public MyXFerModeView(Context context) {
    27         super(context);
    28         initView();
    29         
    30     }
    31     public MyXFerModeView(Context context, AttributeSet attrs) {
    32         super(context, attrs);
    33         initView();
    34         
    35     }
    36     public MyXFerModeView(Context context, AttributeSet attrs, int defStyleAttr) {
    37         super(context, attrs, defStyleAttr);
    38         initView();
    39         
    40     }
    41     /**
    42      * 初始化view
    43      */
    44     public void initView(){
    45         
    46         setLayerType(LAYER_TYPE_SOFTWARE, null);//注意,一定要禁用硬件加速器
    47         
    48         priBmp = BitmapFactory.decodeResource(getResources(), R.drawable.test4);
    49         aftBmp = Bitmap.createBitmap(priBmp.getWidth(), priBmp.getHeight(), Bitmap.Config.ARGB_8888);
    50         
    51         Canvas canvas = new Canvas(aftBmp);
    52         Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//抗锯齿
    53         //矩形,注意应该与priBmp的宽高一致
    54         RectF rect = new RectF(0, 0, priBmp.getWidth(), priBmp.getHeight());
    55         //50和50分别为圆角矩形的圆角弧度(x方向和y方向)
    56         canvas.drawRoundRect(rect, 50, 50, paint);
    57         //为画笔设置xFermode风格,只有具有alpha通道的图片才有效
    58         paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    59         
    60         //画上图片
    61         canvas.drawBitmap(priBmp, 0, 0, paint);
    62         //最后别忘记取消风格
    63         paint.setXfermode(null);
    64         
    65         
    66     }
    67     
    68     @Override
    69     protected void onDraw(Canvas canvas) {
    70         super.onDraw(canvas);
    71         //然后画出新的图片,即aftBmp
    72         canvas.drawBitmap(aftBmp, 5, 5, null);
    73     }
    74 
    75 }

          然后新建imagemode.xml将这个view装进来,代码如下:

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="vertical" 
     6     android:gravity="center">
     7 
     8   <com.fuly.image.MyXFerModeView
     9       android:layout_width="wrap_content"
    10       android:layout_height="wrap_content"/>
    11 
    12 </LinearLayout>

          代码是不是很简单啊,继续往下写,新建活动XFermodeActivity用来将这个布局显示出来,别忘记给这个活动注册哦。代码更简单了,如下:

     1 package com.fuly.image;
     2 
     3 import android.app.Activity;
     4 import android.os.Bundle;
     5 
     6 public class XFermodeActivity extends Activity{
     7     
     8     
     9     protected void onCreate(Bundle savedInstanceState) {
    10     
    11         super.onCreate(savedInstanceState);
    12         setContentView(R.layout.imagemode);
    13         
    14     }
    15 
    16 }

          似乎一切都完成了,不要忘记MainActivity里的按钮事件啊。代码如下:

     1 package com.fuly.image;
     2 
     3 import android.os.Bundle;
     4 import android.view.View;
     5 import android.app.Activity;
     6 import android.content.Intent;
     7 
     8 
     9 public class MainActivity extends Activity {
    10 
    11    
    12     protected void onCreate(Bundle savedInstanceState) {
    13         super.onCreate(savedInstanceState);
    14         setContentView(R.layout.activity_main);
    15     }
    16      
    17     //下面是按钮事件
    18     public void btnMatrix(View v){
    19         Intent intent = new Intent(this,MatrixActivity.class);
    20         startActivity(intent);
    21     }
    22     public void btnXFermode(View v){
    23         Intent intent = new Intent(this,XFermodeActivity.class);
    24         startActivity(intent);
    25     }
    26   
    27 }

          好了,一切都完成了。快运行程序吧。效果如下:

          这样子效果就实现了。其实用xfermode风格可以实现很多常见的效果,需要你去探索。举个例子,记得QQ中我们的头像上传的时候是方形的,但是显示出来的却是圆形的。现在知道为什么了吗?xfermode完全可以实现这个效果。

          好了,相信经过实际代码书写,你已经很好的熟悉了xfermode了。剩下的就需要你自己去探索了。回头看一看,我们的项目中还有三个按钮没有实现效果。所以保存这一节的代码,快快进入下一节吧,利用渲染器实现图片变换。

  • 相关阅读:
    跨域访问方法列举 jsonp 和 客户端
    session 垃圾回收机制
    php 根据数据权重,得分或者持有数量等进行均衡分配给定数量分配方法
    进程和线程比较
    redis 过期策略分析
    redis 基础知识详解
    tcp/ip 协议
    ip 协议详解
    php redis 分布式类
    nginx打开目录游览功能
  • 原文地址:https://www.cnblogs.com/fuly550871915/p/4886455.html
Copyright © 2011-2022 走看看