package org.wp.activity;
import android.app.Activity;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.LinearGradient;
 import android.graphics.Matrix;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Bitmap.Config;
 import android.graphics.PorterDuff.Mode;
 import android.graphics.Shader.TileMode;
 import android.graphics.Paint;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Bundle;
 import android.widget.ImageView;/**
  * ========================================== 
  * Matrix
  * ========================================== 
  * The Matrix class holds a 3x3 matrix for transforming coordinates. 
  * Matrix does not have a constructor, 
  * so it must be explicitly initialized using either reset() 
  * - to construct an identity matrix, 
  * or one of the set..() functions 
  * (e.g. setTranslate, setRotate, etc.).
  *


 * Matrix 中文里叫矩阵,高等数学里有介绍
 * 在图像处理方面,主要是用于平面的缩放、平移、旋转等操作。
 * Matrix的操作,总共分为translate(平移),rotate(旋转),
 * scale(缩放)和skew(倾斜)四种,
 * 每一种变换在Android的API里都提供了set, post和pre三种操作方式
 * 除了translate,其他三种操作都可以指定中心点。
 *

* ========================================== 
  * createBitmap
  * ==========================================
  * public static Bitmap createBitmap (Bitmap source, int x, int y, 
  *      int width, int height, Matrix m, boolean filter) 
  * Since: API Level 1 Returns an immutable bitmap from subset of the 
  *     source bitmap, transformed by the optional matrix. 
  *        It is initialized with the same density as the original bitmap.
  * Parameters
  * source  The bitmap we are subsetting 
  * x  The x coordinate of the first pixel in source 
  * y  The y coordinate of the first pixel in source 
  * width  The number of pixels in each row 
  * height  The number of rows 
  * m  Optional matrix to be applied to the pixels 
  * filter  true if the source should be filtered. 
  *         Only applies if the matrix contains more than 
  *         just translation. 
  * Returns
  * A bitmap that represents the specified subset of source
  * Throws
  * IllegalArgumentException  
  * if the x, y, width, height values are outside of the 
  * dimensions of the source bitmap. 
  *


 * source 源 bitmap对象
 * x 源坐标x位置
 * y 源坐标y位置
 * width 宽度
 * height 高度
 * m 接受的maxtrix对象,如果没有可以设置 为null
 * filter 该参数仅对maxtrix包含了超过一个翻转才有效

* 
  * ==========================================
  * LinearGradient
  * ==========================================
  * public LinearGradient (float x0, float y0, float x1, float y1, i
  *     nt color0, int color1, Shader.TileMode tile) 
  * Since: API Level 1 Create a shader that draws a linear gradient along a line.
  * Parameters
  * x0  The x-coordinate for the start of the gradient line 
  * y0  The y-coordinate for the start of the gradient line 
  * x1  The x-coordinate for the end of the gradient line 
  * y1  The y-coordinate for the end of the gradient line 
  * color0  The color at the start of the gradient line. 
  * color1  The color at the end of the gradient line. 
  * tile  The Shader tiling mode


 *
 * 在android.graphics中我们可以找到有关Gradient字样的类,
 * 比如LinearGradient 线性渐变、RadialGradient径向渐变  和 角度渐变SweepGradient 三种,
 * 他们的基类为android.graphics.Shader。
 *
 * LinearGradient线性渐变
 * 在android平台中提供了两种重载方式来实例化该类分别为,
 * 他们的不同之处为参数中第一种方法可以用颜色数组,和位置来实现更细腻的过渡效果,
 * 比如颜色采样int[] colors数组中存放20种颜色,则渐变将会逐一处理。
 * 而第二种方法参数仅为起初颜色color0和最终颜色color1。

* LinearGradient(float x0, float y0, float x1, float y1, 
  *   int[] colors, float[] positions, Shader.TileMode tile) 
  * LinearGradient(float x0, float y0, float x1, float y1, 
  *   int color0, int color1, Shader.TileMode tile)


 *
 * 参数一为渐变起初点坐标x位置,参数二为y轴位置,
 * 参数三和四分辨对应渐变终点,最后参数为平铺方式,这里设置为镜像
 *
 * 刚才已经讲到Gradient是基于Shader类,
 * 所以我们通过Paint的setShader方法来设置这个渐变
 * p.setShader(lg);
 *
 * ==========================================
 * setXfermode
 * ==========================================
 * Xfermode
 * 可以通过修改Paint的Xfermode来影响在
 * Canvas已有的图像上面绘制新的颜色的方式 。
 *
 * 在正常的情况下,在已有的图像上绘图将会在其上面添加一层新的形状。
 * 如果新的Paint是完全不透明的,那么它将完全遮挡住下面的Paint;
 * 如果它是部分透明的,那么它将会被染上下面的颜色。
 *
 * 下面的Xfermode子类可以改变这种行为:

* 
  * AvoidXfermode  指定了一个颜色和容差,
  *           强制Paint避免在它上面绘图(或者只在它上面绘图)。
  * PixelXorXfermode  当覆盖已有的颜色时,应用一个简单的像素XOR操作。
  * 
  * PorterDuffXfermode  这是一个非常强大的转换模式,使用它,
  *                     可以使用图像合成的16条Porter-Duff规则的任意
  *                     一条来控制Paint如何与已有的Canvas图像进行交互。
  * 
  * 16条Porter-Duff规则
  * 1.PorterDuff.Mode.CLEAR
  * 2.PorterDuff.Mode.SRC
  * 3.PorterDuff.Mode.DST
  * 4.PorterDuff.Mode.SRC_OVER
  * 5.PorterDuff.Mode.DST_OVER
  * 6.PorterDuff.Mode.SRC_IN
  * 7.PorterDuff.Mode.DST_IN
  * 8.PorterDuff.Mode.SRC_OUT
  * 9.PorterDuff.Mode.DST_OUT
  * 10.PorterDuff.Mode.SRC_ATOP
  * 11.PorterDuff.Mode.DST_ATOP
  * 12.PorterDuff.Mode.XOR
  * 13.PorterDuff.Mode.DARKEN
  * 14.PorterDuff.Mode.LIGHTEN
  * 15.PorterDuff.Mode.MULTIPLY
  * 16.PorterDuff.Mode.SCREEN 
  * 
  * @author wp
  */
 public class MainActivity extends Activity { @Override
  public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);  ImageView myImageView = (ImageView) this.findViewById(R.id.myImageView);
   Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(
     R.drawable.qianqian)).getBitmap();
   myImageView.setImageBitmap(createReflectedImage(bitmap));
  } private Bitmap createReflectedImage(Bitmap originalBitmap) {
   // 图片与倒影间隔距离
   final int reflectionGap = 4;
   
   // 图片的宽度
   int width = originalBitmap.getWidth();
   // 图片的高度
   int height = originalBitmap.getHeight();
   
   Matrix matrix = new Matrix();
   // 图片缩放,x轴变为原来的1倍,y轴为-1倍,实现图片的反转
   matrix.preScale(1, -1);
   // 创建反转后的图片Bitmap对象,图片高是原图的一半。
   Bitmap reflectionBitmap = Bitmap.createBitmap(originalBitmap, 0,
     height / 2, width, height / 2, matrix, false);
   // 创建标准的Bitmap对象,宽和原图一致,高是原图的1.5倍。
   Bitmap withReflectionBitmap = Bitmap.createBitmap(width, (height
     + height / 2 + reflectionGap), Config.ARGB_8888);  // 构造函数传入Bitmap对象,为了在图片上画图
   Canvas canvas = new Canvas(withReflectionBitmap);
   // 画原始图片
   canvas.drawBitmap(originalBitmap, 0, 0, null);  // 画间隔矩形
   Paint defaultPaint = new Paint();
   canvas.drawRect(0, height, width, height + reflectionGap, defaultPaint);  // 画倒影图片
   canvas.drawBitmap(reflectionBitmap, 0, height + reflectionGap, null);  // 实现倒影效果
   Paint paint = new Paint();
   LinearGradient shader = new LinearGradient(0, originalBitmap.getHeight(), 
     0, withReflectionBitmap.getHeight(), 0x70ffffff, 0x00ffffff,
     TileMode.MIRROR);
   paint.setShader(shader);
   paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));  // 覆盖效果
   canvas.drawRect(0, height, width, withReflectionBitmap.getHeight(), paint);  return withReflectionBitmap;
  }
 }