關(guān)于PorterDuff.Mode的一點理解

寫過自定義view的小伙伴們可能了解或者是用到過PorterDuff.Mode阻塑,第一次接觸這個東西的時候蓝撇,就感覺這玩意兒挺魔性,可以玩一把陈莽。于是乎就查找了一些關(guān)于PorterDuff.Mode的資料以及一些小Demo渤昌,印象最深的應(yīng)該還是刮獎的那個。廢話不多說走搁,下面就說說我對PorterDuff.Mode的理解和體會独柑,僅代表個人觀點,如有錯誤希望大家指正私植。

    1. PorterDuff.Mode是什么忌栅?
      在android SDK Paint類中有一個很重要的方法setXfermode,這個方法用于設(shè)置圖像的過渡模式曲稼,所謂過渡是指圖像的飽和度索绪、顏色值等參數(shù)的計算結(jié)果的圖像表現(xiàn)。在SDK中Xfermode有三個子類:AvoidXfermode, PixelXorXfermode和PorterDuffXfermode贫悄,前兩個類在API 16被遺棄了瑞驱,所以這里不作介紹。PorterDuffXfermode類主要用于圖形合成時的圖像過渡模式計算窄坦,其概念來自于1984年在ACM SIGGRAPH計算機圖形學(xué)出版物上發(fā)表了“Compositing digital images(合成數(shù)字圖像)”的Tomas Porter和Tom Duff唤反,合成圖像的概念極大地推動了圖形圖像學(xué)的發(fā)展,PorterDuffXfermode類名就來源于這倆人的名字組合PorterDuff鸭津。下面是android SDK中PorterDuff的Mode枚舉類型定義彤侍。
public enum Mode {
    /** [0, 0] */
    CLEAR       (0),
    /** [Sa, Sc] */
    SRC         (1),
    /** [Da, Dc] */
    DST         (2),
    /** [Sa + (1 - Sa)*Da, Rc = Sc + (1 - Sa)*Dc] */
    SRC_OVER    (3),
    /** [Sa + (1 - Sa)*Da, Rc = Dc + (1 - Da)*Sc] */
    DST_OVER    (4),
    /** [Sa * Da, Sc * Da] */
    SRC_IN      (5),
    /** [Sa * Da, Sa * Dc] */
    DST_IN      (6),
    /** [Sa * (1 - Da), Sc * (1 - Da)] */
    SRC_OUT     (7),
    /** [Da * (1 - Sa), Dc * (1 - Sa)] */
    DST_OUT     (8),
    /** [Da, Sc * Da + (1 - Sa) * Dc] */
    SRC_ATOP    (9),
    /** [Sa, Sa * Dc + Sc * (1 - Da)] */
    DST_ATOP    (10),
    /** [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] */
    XOR         (11),
    /** [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + min(Sc, Dc)] */
    DARKEN      (12),
    /** [Sa + Da - Sa*Da, Sc*(1 - Da) + Dc*(1 - Sa) + max(Sc, Dc)] */
    LIGHTEN     (13),
    /** [Sa * Da, Sc * Dc] */
    MULTIPLY    (14),
    /** [Sa + Da - Sa * Da, Sc + Dc - Sc * Dc] */
    SCREEN      (15),
    /** Saturate(S + D) */
    ADD         (16),
    OVERLAY     (17);
    Mode(int nativeInt) {
        this.nativeInt = nativeInt;
    }
    /**
     * @hide
     */
    public final int nativeInt;
}  

上面代碼中每種模式的注釋都說明了該模式的alpha通道和顏色值的計算方式,要理解各個模式的計算方式需要先弄明白公式中各個元素的具體含義:

Sa:全稱為Source alpha逆趋,表示源圖的Alpha通道盏阶;
Sc:全稱為Source color,表示源圖的顏色闻书;
Da:全稱為Destination alpha般哼,表示目標圖的Alpha通道吴汪;
Dc:全稱為Destination color,表示目標圖的顏色.

當Alpha通道的值為1時蒸眠,圖像完全可見;當Alpha通道值為0時杆融,圖像完全不可見楞卡;當Alpha通道的值介于0和1之間時,圖像只有一部分可見脾歇。Alpha通道描述的是圖像的形狀蒋腮,而不是透明度。

  • 2.什么是源圖什么是目標圖藕各?
    源圖:其實就是你即將要繪制在當前畫布上的圖池摧。
    目標圖:就是你在進行下一步繪制之前當前畫布對應(yīng)繪制區(qū)域的圖;
    以下是Google官方Sample中給的16種模式下合成的效果圖,事實上Google在這兒是挖了一個坑的(兩次繪制的圖像都是從最左頂點開始激况,繪制圖形的寬高也寫的是不同的作彤,具體詳細解釋請戳:http://blog.csdn.net/iispring/article/details/50472485),真實的合成樣子并不完全是這樣的乌逐;
    image.png

    這才是真實的合成效果(藍色的繪制起點是從黃色的圓心處):
    image.png
  • 3.PorterDuff.Mode的用法以及一個刮獎小Demo
package com.ebanswers.iqcore;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by air on 2017/8/23.
 */

public class GuaJiangView extends View {

   private Bitmap mBitmap;
    private Bitmap mDstBitmap;
    private Canvas mCanvas;
    private Path mPath;
    private Paint paint;

    public GuaJiangView(Context context) {
        this(context, null);
    }

    public GuaJiangView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public GuaJiangView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    private void initView() {
        //創(chuàng)建一個bitmap(一張圖片)
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.picture);
        //根據(jù)上面的bitmap創(chuàng)建相同大小的bitmap,此時改bitmap所有的像素點的顏色值全為0竭讳,即全透明的一個bitmap
        mDstBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        //創(chuàng)建一個Path對象,后面根據(jù)手的touch事件設(shè)置path
        mPath = new Path();
        paint = new Paint();
        paint.setAntiAlias(true);//抗鋸齒
        paint.setDither(true);//防止抖動
        paint.setAlpha(0);//設(shè)置Alpha為0
        paint.setStyle(Paint.Style.STROKE);//設(shè)置風格為描邊
        paint.setStrokeWidth(50);//設(shè)置描邊的寬度
        paint.setStrokeCap(Paint.Cap.ROUND);//設(shè)置筆觸為圓角
        paint.setStrokeJoin(Paint.Join.ROUND);//設(shè)置繪制轉(zhuǎn)折的的地方為圓角
        mCanvas = new Canvas(mDstBitmap);//創(chuàng)建一個畫布在透明的bitmap上進行繪制
        mCanvas.drawColor(Color.GRAY);//將透明的bitmap繪制成灰色的浙踢,所有像素點的色值對應(yīng)灰色的值
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //第一步繪制一個圖片
        canvas.drawBitmap(mBitmap, 0, 0, null);
        //在灰色的bitmap上繪制路徑
        drawTouchPath();
        //將灰色的bitmap繪制到原畫布上
        canvas.drawBitmap(mDstBitmap, 0, 0, null);
    }

    /**
     * 關(guān)鍵點绢慢,繪制手指的touch路徑
     */
    private void drawTouchPath() {
        /*
         * 手指觸摸后繪制觸摸路徑,在執(zhí)行此操作時候
         * 第一次mDstBitmap全部像素色值是灰色(mCanvas.drawColor(Color.GRAY))----目標圖(當前畫布上的圖)
         * 將要繪制的路徑mPath----源圖(將要繪制的圖)
         * 模式為:PorterDuff.Mode.DST_IN(這里DST_IN的IN即是數(shù)學(xué)中的交集的意思洛波,指針對mPath和mDstBitmap的交集進行合成胰舆,實際上就是mPath)
         * 該模式的算法[Sa * Da, Sa * Dc]
         * 目標圖(灰色)的透明度通道為1即Da為1,Dc為灰色的色值
         * 源圖(畫筆設(shè)置了Alpha為0),即(mPath繪制的區(qū)域)Sa為0
         * 在mPath繪制的區(qū)域內(nèi)目標圖Da =1,Dc = Color.GRAY,源圖Sa = 0;
         * 則[Sa * Da, Sa * Dc] = [0*1,0*Color.GRAY]=[0,0]
         * 即mPath區(qū)域內(nèi)是全透明的
         */
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mCanvas.drawPath(mPath, paint);
    }


    /**
     * 根據(jù)touch事件記錄手指的觸摸路徑
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        float x = event.getX();
        float y = event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mPath.reset();
                mPath.moveTo(x, y);
                break;
            case MotionEvent.ACTION_MOVE:
                mPath.lineTo(x, y);
                break;
        }
        invalidate();
        return true;
    }
}  
  • 4.解釋已經(jīng)在代碼中進行注釋了蹬挤,運行結(jié)果圖如下:

image.png

中獎了一個妹紙缚窿;
最后還要感謝一下各位,獲益匪淺:
http://blog.csdn.net/iispring/article/details/50472485
http://www.reibang.com/p/d11892bbe055

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末闻伶,一起剝皮案震驚了整個濱河市滨攻,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蓝翰,老刑警劉巖光绕,帶你破解...
    沈念sama閱讀 219,039評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異畜份,居然都是意外死亡诞帐,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評論 3 395
  • 文/潘曉璐 我一進店門爆雹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來停蕉,“玉大人愕鼓,你說我怎么就攤上這事』燮穑” “怎么了菇晃?”我有些...
    開封第一講書人閱讀 165,417評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蚓挤。 經(jīng)常有香客問我磺送,道長,這世上最難降的妖魔是什么灿意? 我笑而不...
    開封第一講書人閱讀 58,868評論 1 295
  • 正文 為了忘掉前任估灿,我火速辦了婚禮,結(jié)果婚禮上缤剧,老公的妹妹穿的比我還像新娘馅袁。我一直安慰自己,他們只是感情好荒辕,可當我...
    茶點故事閱讀 67,892評論 6 392
  • 文/花漫 我一把揭開白布汗销。 她就那樣靜靜地躺著,像睡著了一般兄纺。 火紅的嫁衣襯著肌膚如雪大溜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評論 1 305
  • 那天估脆,我揣著相機與錄音钦奋,去河邊找鬼。 笑死疙赠,一個胖子當著我的面吹牛付材,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播圃阳,決...
    沈念sama閱讀 40,416評論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼位岔,長吁一口氣:“原來是場噩夢啊……” “哼赂乐!你這毒婦竟也來了黄痪?” 一聲冷哼從身側(cè)響起沉衣,我...
    開封第一講書人閱讀 39,326評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锣夹,沒想到半個月后页徐,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,782評論 1 316
  • 正文 獨居荒郊野嶺守林人離奇死亡银萍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,957評論 3 337
  • 正文 我和宋清朗相戀三年变勇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贴唇。...
    茶點故事閱讀 40,102評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡搀绣,死狀恐怖飞袋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情链患,我是刑警寧澤巧鸭,帶...
    沈念sama閱讀 35,790評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站锣险,受9級特大地震影響蹄皱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芯肤,卻給世界環(huán)境...
    茶點故事閱讀 41,442評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望压鉴。 院中可真熱鬧崖咨,春花似錦、人聲如沸油吭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婉宰。三九已至歌豺,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間心包,已是汗流浹背类咧。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蟹腾,地道東北人痕惋。 一個月前我還...
    沈念sama閱讀 48,332評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像娃殖,于是被迫代替她去往敵國和親值戳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,044評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 在Paint中有很多的屬性可以設(shè)置炉爆,比如可以設(shè)置陰影堕虹,顏色過濾等等,這些會產(chǎn)生不同的奇妙效果芬首,今天就對各種屬性探索...
    Jwennnnnnnnnn閱讀 2,373評論 0 2
  • 做過圖形圖像處理coding的Android程序員一定用過或了解過PorterDuff.Mode這個枚舉變量中的某...
    Alexyz123閱讀 62,442評論 27 154
  • 位圖圖像和圖像蒙板就像Quartz中的任何圖形圖元赴捞。 Quartz中的圖像和圖像蒙板都由CGImageRef數(shù)據(jù)類...
    權(quán)宜平和閱讀 1,681評論 0 3
  • 目錄 [Paint 之 Font](#Paint 之 Font) 姿勢點 在Android中設(shè)置數(shù)字類型的參數(shù)時如...
    北疆_閱讀 632評論 0 2
  • 信息時代,擅長邏輯思考衩辟、線性分析的知識工作者占據(jù)主導(dǎo)地位螟炫。然后,隨著物質(zhì)的富裕和工作全球化艺晴,世界正在發(fā)生巨大的變化...
    小喜悅閱讀 1,577評論 0 0