實(shí)現(xiàn)圖片的濾鏡效果

提到這個(gè)到不是因?yàn)橐稣掌幚碥浖臑V鏡效果设联,而是開發(fā)過程中設(shè)計(jì)師每每只提供一張icon圖標(biāo)恕曲,然后說點(diǎn)擊效果你自己用程序?qū)崿F(xiàn)吧;或者產(chǎn)品經(jīng)理過來說飒筑,用戶頭像加個(gè)點(diǎn)擊效果吧片吊。以往的開發(fā)過程中,設(shè)計(jì)師多半會(huì)提供兩張icon圖標(biāo)协屡,一張正常狀態(tài)俏脊,一張選中狀態(tài),這樣點(diǎn)擊的時(shí)候會(huì)有一個(gè)動(dòng)態(tài)的效果肤晓。而現(xiàn)在一張圖去實(shí)現(xiàn)點(diǎn)擊效果還真有點(diǎn)難為了爷贫,車到山前必有路,誰讓我是老司機(jī)呢补憾。
首先我印象中Imageview會(huì)有個(gè)透明度Alpha的屬性漫萄,于是我最先想到用setAlpha()來改變圖片的透明度,但實(shí)際效果并不好盈匾。后來在Stay的點(diǎn)撥下終于找到了比較好的解決方案腾务,ImageView有一個(gè)setColorFilter()的API,完全適合當(dāng)前場景削饵。

  /**
     * Set a tinting option for the image.
     * 
     * @param color Color tint to apply.
     * @param mode How to apply the color.  The standard mode is
     * {@link PorterDuff.Mode#SRC_ATOP}
     * 
     * @attr ref android.R.styleable#ImageView_tint
     */
    public final void setColorFilter(int color, PorterDuff.Mode mode) {
        setColorFilter(new PorterDuffColorFilter(color, mode));
    }

    /**
     * Set a tinting option for the image. Assumes
     * {@link PorterDuff.Mode#SRC_ATOP} blending mode.
     *
     * @param color Color tint to apply.
     * @attr ref android.R.styleable#ImageView_tint
     */
    @RemotableViewMethod
    public final void setColorFilter(int color) {
        setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
    }
    /**
     * Apply an arbitrary colorfilter to the image.
     *
     * @param cf the colorfilter to apply (may be null)
     *
     * @see #getColorFilter()
     */
    public void setColorFilter(ColorFilter cf) {
        if (mColorFilter != cf) {
            mColorFilter = cf;
            mColorMod = true;
            applyColorMod();
            invalidate();
        }
    }

setColorFilter有以上三種調(diào)用方式岩瘦,可以直接傳入色值和mode,mode缺省的默認(rèn)值為PorterDuff.Mode.SRC_ATOP窿撬,具體各mode的效果可以參見http://blog.sina.com.cn/s/blog_5da93c8f01012pkj.html启昧, setColorFilter還可以傳入ColorFilter的子類。

ColorFilter有三個(gè)子類ColorMatrixColorFilter劈伴,LightingColorFilter箫津,PorterDuffColorFilter,它的功能應(yīng)該就是按照一定的規(guī)則改變圖片的顏色宰啦,三個(gè)子類各有各的不同的改法規(guī)則苏遥,其中ColorMatrixColorFilter的改變法則就是ColorMatrix的改變規(guī)則,它是ColorMatrix的應(yīng)用赡模。LightingColorFilter 乘以第一個(gè)顏色的RGB通道田炭,然后加上第二個(gè)顏色。每一次轉(zhuǎn)換的結(jié)果都限制在0到255之間漓柑。PorterDuffColorFilter 可以使用數(shù)字圖像合成的16條Porter-Duff 規(guī)則中的任意一條來向Paint應(yīng)用一個(gè)指定的顏色教硫。

我們就挑第一個(gè)ColorMatrixColorFilter來舉例叨吮,前面已經(jīng)說過,ColorMatrixColorFilter的改變法則就是ColorMatrix的改變規(guī)則瞬矩,它是ColorMatrix的應(yīng)用茶鉴。ColorMatrix是Android源碼中一個(gè)顏色矩陣類,通過對這個(gè)類的一系列操作景用,可以控制改變圖片的色調(diào)明暗飽和度等涵叮,這也就是圖片處理軟件實(shí)現(xiàn)濾鏡效果的原理。這個(gè)類把顏色定義為一個(gè)4*5的矩陣伞插,如果用一個(gè)一緯數(shù)組表示就是這樣:
[ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ]割粮。

/** 
*  4x5 matrix for transforming the color+alpha components of a Bitmap. 
*  The matrix is stored in a single array, and its treated as follows: 
*  [ a, b, c, d, e, 
*    f, g, h, i, j, 
*    k, l, m, n, o,
*    p, q, r, s, t ] 
* * When applied to a color [r, g, b, a], the resulting color is computed as * (after clamping) 
*   R' = a*R + b*G + c*B + d*A + e; 
*   G' = f*R + g*G + h*B + i*A + j; 
*   B' = k*R + l*G + m*B + n*A + o; 
*   A' = p*R + q*G + r*B + s*A + t; 
*/

這里是源碼里的注釋,已經(jīng)解釋的很清楚了媚污,RGBA的運(yùn)算公式也清晰明了舀瓢,所以實(shí)際調(diào)用過程中,我們可以通過傳入需要的參數(shù)來控制RGBA的值耗美,進(jìn)而改變圖片的色彩京髓。

/** 
* Set this colormatrix to identity: 
* [ 1 0 0 0 0   - red vector 
*   0 1 0 0 0   - green vector
*   0 0 1 0 0   - blue vector 
*   0 0 0 1 0 ] - alpha vector 
*/

這里是一張圖片的默認(rèn)色彩屬性值,我們只需要根據(jù)需求去調(diào)校各參數(shù)值商架,就能實(shí)現(xiàn)圖片的濾鏡效果了朵锣。再回到最開始的訴求,我是想通過程序?qū)崿F(xiàn)單張圖片的點(diǎn)擊效果甸私,但是設(shè)計(jì)師只提供了一張圖诚些,那么我只需要在手指按下的時(shí)候去給當(dāng)前圖片加個(gè)濾鏡,抬起時(shí)再移除即可皇型。簡單粗暴點(diǎn)诬烹,直接上代碼。

/**
 * Created by yx on 16/4/3.
 */
public class DiscolorImageView extends ImageView{


    /**
     * 變暗
     */
    private final float[] SELECTED_DARK = new float[]
            {1, 0, 0, 0, -80,
            0, 1, 0, 0, -80,
            0, 0, 1, 0, -80,
            0, 0, 0, 1, 0};
    /**
     * 變亮
     */

    private final float[] SELECTED_BRIGHT = new float[]
            {1, 0, 0, 0, 80,
                    0, 1, 0, 0, 80,
                    0, 0, 1, 0, 80,
                    0, 0, 0, 1, 0};

    /**
     * 高對比度
     */

    private final float[] SELECTED_HDR = new float[]
            {5, 0, 0, 0, -250,
                    0, 5, 0, 0, -250,
                    0, 0, 5, 0, -250,
                    0, 0, 0, 1, 0};

    /**
     * 高飽和度
     */
    private final float[] SELECTED_HSAT = new float[]
            {(float) 3, (float) -2, (float) -0.2, 0, 50,
                    -1, 2, -0, 0, 50,
                    -1, -2, 4, 0, 50,
                    0, 0, 0, 1, 0};

    /**
     * 改變色調(diào)
     */
    private final float[] SELECTED_DISCOLOR = new float[]
            {(float) -0.5, (float) -0.6, (float) -0.8, 0, 0,
                    (float) -0.4, (float) -0.6, (float) -0.1, 0, 0,
                    (float) -0.3, 2, (float) -0.4, 0, 0,
                    0, 0, 0, 1, 0};

    public DiscolorImageView(Context context) {
        super(context);
        this.setOnTouchListener(VIEW_TOUCH_DISCOLOR);
    }

    public DiscolorImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.setOnTouchListener(VIEW_TOUCH_DISCOLOR);
    }

    public DiscolorImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        this.setOnTouchListener(VIEW_TOUCH_DISCOLOR);
    }

    public OnTouchListener VIEW_TOUCH_DISCOLOR = new OnTouchListener() {


        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                ImageView iv = (ImageView) v;
                iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_HDR));
              //iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_BRIGHT));
              //iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_HDR));
              //iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_HSAT));
              //iv.setColorFilter(new ColorMatrixColorFilter(SELECTED_DISCOLOR));
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                ImageView iv = (ImageView) v;
                iv.clearColorFilter();
                mPerformClick();
            } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
                ImageView iv = (ImageView) v;
                iv.clearColorFilter();
            }
            return true;

        }
    };

        private void mPerformClick() {
            DiscolorImageView.this.performClick();
        }
    }

我這里隨便給出了幾個(gè)濾鏡效果的參數(shù)值弃鸦,但是未經(jīng)調(diào)教绞吁,有可能效果一塌糊涂,基本原理很簡單了唬格,又要說到onTouch事件了家破,按下去的時(shí)候顯示濾鏡效果圖,抬起時(shí)移除濾鏡顯示原圖购岗,這樣點(diǎn)擊的時(shí)候就有了一個(gè)動(dòng)態(tài)的selector效果了汰聋。如下圖:

device-2016-04-06-004225.gif
device-2016-04-06-004356.gif

device-2016-04-06-004437.gif

參考資料:
http://blog.sina.com.cn/s/blog_5da93c8f01012pkj.htm
http://my.oschina.net/gavinjin/blog/208586

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市喊积,隨后出現(xiàn)的幾起案子烹困,更是在濱河造成了極大的恐慌,老刑警劉巖乾吻,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件髓梅,死亡現(xiàn)場離奇詭異拟蜻,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)枯饿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門酝锅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人奢方,你說我怎么就攤上這事搔扁。” “怎么了袱巨?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碳抄。 經(jīng)常有香客問我愉老,道長,這世上最難降的妖魔是什么剖效? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任嫉入,我火速辦了婚禮,結(jié)果婚禮上璧尸,老公的妹妹穿的比我還像新娘咒林。我一直安慰自己,他們只是感情好爷光,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布垫竞。 她就那樣靜靜地躺著,像睡著了一般蛀序。 火紅的嫁衣襯著肌膚如雪欢瞪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天徐裸,我揣著相機(jī)與錄音遣鼓,去河邊找鬼。 笑死重贺,一個(gè)胖子當(dāng)著我的面吹牛骑祟,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播气笙,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼次企,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了潜圃?” 一聲冷哼從身側(cè)響起抒巢,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秉犹,沒想到半個(gè)月后蛉谜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體稚晚,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年型诚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了客燕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狰贯,死狀恐怖也搓,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情涵紊,我是刑警寧澤傍妒,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布,位于F島的核電站摸柄,受9級特大地震影響颤练,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜驱负,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一嗦玖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧跃脊,春花似錦宇挫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至绘雁,卻和暖如春娱局,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背咧七。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工衰齐, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人继阻。 一個(gè)月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓耻涛,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

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

  • 濾鏡 濾鏡俊嗽;主要是用來實(shí)現(xiàn)圖像的各種特殊效果。它在Photoshop中具有非常神奇的作用卓研。濾鏡通常需要同通道、圖層...
    fengzhizi715閱讀 4,720評論 3 12
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫、插件奏赘、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,066評論 4 62
  • 別看我每天發(fā)自拍,其實(shí)是越不自信的自己梁只,越懷疑自己缚柳,才要看看我自己 一個(gè)對自我有充分了解的人,是不會(huì)像我這樣搪锣,不知...
    愛嬌閱讀 240評論 0 0
  • “媽媽秋忙,去給我買豆腐腦吧」怪郏” “不去灰追,想吃自己去!” 被硬邦邦的話拒絕后旁壮,我翻身下床直接進(jìn)了廚房监嗜,決定自己做頓早餐...
    葵花島楊亞寧閱讀 726評論 0 4