1.MainActivity類:
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; } }
效果圖:
2.setXfermode
設置兩張圖片相交時的模式
我們知道 在正常的情況下,在已有的圖像上繪圖將會在其上面添加一層新的形狀。 如果新的Paint是完全不透明的,那麼它將完全遮擋住下面的Paint;
而setXfermode就可以來解決這個問題
一般來說 用法是這樣的
Canvas canvas = new Canvas(bitmap1); paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); canvas.drawBitmap(mask, 0f, 0f, paint);
canvas原有的圖片 可以理解爲背景 就是dst
新畫上去的圖片 可以理解爲前景 就是src
Mode的值 如下圖
一個遮罩層的具體例子 參見
http://lonesane.iteye.com/blog/791267