圖片相交模式 setXfermode

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 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *