MainActivity
Java代碼
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 3×3 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;
}
}
================================================================================================================================
原文地址https://lipeng88213.iteye.com/blog/1189452
setXfermode
設置兩張圖片相交時的模式
我們知道 在正常的情況下,在已有的圖像上繪圖將會在其上面添加一層新的形狀。 如果新的Paint是完全不透明的,那麼它將完全遮擋住下面的Paint;
而setXfermode就可以來解決這個問題
一般來說 用法是這樣的
Java代碼
Canvas canvas = new Canvas(bitmap1);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(mask, 0f, 0f, paint);
就是在圖片bitmap1上面繪制圖片mask時 處理兩者相交時候顯示的問題
canvas原有的圖片 可以理解為背景 就是dst
新畫上去的圖片 可以理解為前景 就是src