Android開發(fā)之圖像處理那點(diǎn)事——變換

繼上一篇《Android開發(fā)之圖像處理那點(diǎn)事——濾鏡》,這次我們來(lái)講一下圖片的變換操作阻星,本篇主要是介紹常見的圖像變換4種操作(平移、縮放已添、旋轉(zhuǎn)妥箕、錯(cuò)切)

對(duì)于圖像的顏色處理,Andriod系統(tǒng)給我們提供一個(gè)很方便的顏色矩陣類ColorMatrix更舞,同樣的畦幢,Android系統(tǒng)也給圖像的變換處理提供了矩陣類Matrix,相比顏色矩陣的4 * 5缆蝉,變換矩陣來(lái)得更加簡(jiǎn)單宇葱,它是由一個(gè)3 * 3的數(shù)字矩陣組成瘦真,我們來(lái)了解一下變換原理。

變換矩陣

在上一篇文章中黍瞧,我們講到像素點(diǎn)的顏色是由RGBA1組成的诸尽,分別代表紅、綠印颤、藍(lán)您机、透明度各通道值還有顏色偏移量,在變換矩陣中也是類似的年局,像素點(diǎn)的位置是由矩陣C(X际看、Y、L)組成的矢否,分別代表像素點(diǎn)在X仲闽、Y軸的位置還有偏移量。

變換矩陣

根據(jù)矩陣的乘法僵朗,我們可以得出下面的等式:

X1 = a * X + b * Y + c
Y1 = d * X + e * Y + f
L  = g * X + h * Y + i

當(dāng)a=1赖欣,b和c=0,可以知道X1=1X+0+0=1X验庙,
當(dāng)e=1畏鼓,d和f=0,可以知道Y1=0+1Y+0=1Y
當(dāng)i=1壶谒,g和h=0,可以知道1=0+0+1=1
由此我們可以得到變換矩陣的單位矩陣:

單位矩陣

在日常開發(fā)中膳沽,我們涉及到的圖像變換大致有平移汗菜、縮放、旋轉(zhuǎn)挑社、錯(cuò)切(很少)陨界,這些操作就是對(duì)這3 * 3的矩陣做數(shù)值上的調(diào)整,和上一篇講顏色矩陣變化是類似的痛阻,不清楚的朋友菌瘪,具體可以參考上一篇文章的講解,下面我們快速過(guò)一下流程阱当。

平移操作

像素點(diǎn)的平移其實(shí)就是對(duì)像素點(diǎn)的x和y坐標(biāo)進(jìn)行移動(dòng)俏扩,如下圖,從點(diǎn)p1移動(dòng)到點(diǎn)p弊添,假設(shè)p1(x1录淡,y1)分別平移了x0和y0距離得到p(x,y)油坝,

平移操作

得到的公式就是:

x = x1 + x0
y = y1 + y0

矩陣所表現(xiàn)出來(lái)的形式:

平移操作

縮放操作

對(duì)于單個(gè)像素點(diǎn)是不存在縮放操作的嫉戚,但如果是一系列的像素點(diǎn)刨裆,我們就可以根據(jù)x和y軸做一定比例的縮放,假設(shè)縮放比例為K1彬檀,得到的公式是:

x = K1 * x0
y = k1 * y0

矩陣所表現(xiàn)出來(lái)的形式:

縮放操作

旋轉(zhuǎn)操作

像素點(diǎn)的旋轉(zhuǎn)是圍繞一個(gè)點(diǎn)旋轉(zhuǎn)一定的角度得到新的像素點(diǎn)位置帆啃,為了便于理解,這里帶上一張圖:

旋轉(zhuǎn)操作

如上圖以原點(diǎn)為中心旋轉(zhuǎn)窍帝,點(diǎn)(x0努潘,y0)旋轉(zhuǎn)了β°角度到了p(x,y)盯桦,假設(shè)斜邊為r慈俯,根據(jù)三角函數(shù)我們可以知道:

x0 = r * cosα
y0 = r * sinα

那么x和y就是x0和y0旋轉(zhuǎn)了α角度后,再旋轉(zhuǎn)了β角度拥峦,根據(jù)三角函數(shù)可以推出:

x = r * cos(α + β) = r * cosα * cosβ - r * sinα * sinβ = x0 * cosβ - y0 * sinβ
y = r * sin(α + β) = r * sinα * cosβ + r * cosα * sinβ =  y0 * cosβ + x0 * sinβ

將上面的式子代入贴膘,根據(jù)推導(dǎo)公式,我們可以知道矩陣的表現(xiàn)形式為:

旋轉(zhuǎn)操作

錯(cuò)切操作

這個(gè)平時(shí)用的比較少略号,大概了解一下就可以刑峡,錯(cuò)切分為水平錯(cuò)切和垂直錯(cuò)切。

水平錯(cuò)切效果就是讓所有像素點(diǎn)的Y軸坐標(biāo)不變玄柠,X軸坐標(biāo)按照比例進(jìn)行平移突梦,且平移的大小與該點(diǎn)到Y(jié)軸的距離成成正比,計(jì)算公式為:

x = x0 + k1 * y0
y = y0

矩陣變現(xiàn)形式為:

水平錯(cuò)切

垂直錯(cuò)切讓所有像素點(diǎn)的X軸坐標(biāo)不變羽利,Y軸坐標(biāo)按照比例進(jìn)行平移宫患,且平移的大小與該點(diǎn)到X軸的距離成成正比,計(jì)算公式為:

x = x0 
y = y0+ k2 * x0

矩陣變現(xiàn)形式為:

垂直錯(cuò)切

兩個(gè)方向都錯(cuò)切这弧,公式為:

x = x0 + k1 * y0
y = k2 * x0 * y0
水平/垂直錯(cuò)切

根據(jù)以上的矩陣表現(xiàn)方式娃闲,我們可以推出圖像的變換規(guī)律為:

矩陣變換規(guī)律

Matrix

了解了各種變換原理后,我們來(lái)看下Matrix類匾浪,這是Android系統(tǒng)給我們提供的圖像變換矩陣類皇帮,打開源碼,我們可以看到這9個(gè)常量:

    public static final int MSCALE_X = 0;   //!< use with getValues/setValues
    public static final int MSKEW_X  = 1;   //!< use with getValues/setValues
    public static final int MTRANS_X = 2;   //!< use with getValues/setValues
    public static final int MSKEW_Y  = 3;   //!< use with getValues/setValues
    public static final int MSCALE_Y = 4;   //!< use with getValues/setValues
    public static final int MTRANS_Y = 5;   //!< use with getValues/setValues
    public static final int MPERSP_0 = 6;   //!< use with getValues/setValues
    public static final int MPERSP_1 = 7;   //!< use with getValues/setValues
    public static final int MPERSP_2 = 8;   //!< use with getValues/setValues

我們把它按3 * 3的矩陣形式排開蛋辈,可以得到:

矩陣

對(duì)比下剛才上面我們推導(dǎo)的矩陣表現(xiàn)形式属拾,怎么樣,是不是更有感覺了冷溶,我們可以得到如下信息:
MTRANS_X渐白、MTRANS_Y 決定了平移(Translate)
MSCALE_X、MSCALE_Y 決定了縮放( Scale)
MSCALE_X逞频、MSKEW_X礼预、MSCALE_Y、MSKEW_Y 決定了旋轉(zhuǎn)( Rotate)
MSKEW_X虏劲、MSKEW_Y 決定了錯(cuò)切( Skew)
其實(shí)圖像的變換操作無(wú)非就是對(duì)這個(gè)3 * 3的矩陣進(jìn)行值的變化托酸,而Matrix類只是幫我們封裝好了這些操作褒颈,讓我們無(wú)需關(guān)心細(xì)節(jié),更加專注業(yè)務(wù)的實(shí)現(xiàn)励堡,我們可以在Matrix中找到各操作對(duì)應(yīng)的調(diào)用方法:

矩陣的操作方法

簡(jiǎn)單的看個(gè)小Demo:

上面分別對(duì)圖像進(jìn)行了平移谷丸、縮放、旋轉(zhuǎn)应结、錯(cuò)切操作刨疼,貼一下核心代碼:

            Matrix matrix = new Matrix();
            matrix.setTranslate(50, 50);//x,y坐標(biāo)平移50像素
            canvas.drawBitmap(mBitmap, matrix, null);
            Matrix matrix = new Matrix();
            matrix.setScale(2, 2);//x鹅龄,y坐標(biāo)放大原來(lái)2倍
            canvas.drawBitmap(mBitmap, matrix, null);
            Matrix matrix = new Matrix();
            matrix.setRotate(20);//x揩慕,y坐標(biāo)旋轉(zhuǎn)20度
            canvas.drawBitmap(mBitmap, matrix, null);
            Matrix matrix = new Matrix();
            matrix.setSkew(2, 2);//x,y坐標(biāo)按比例錯(cuò)切平移2
            canvas.drawBitmap(mBitmap, matrix, null);

當(dāng)然這些操作也是可以組合起來(lái)的扮休,Matrix里提供了一系列的postXXX迎卤,preXXX方法:

矩陣的操作方法

其實(shí)就是線性代數(shù)中矩陣的左乘和右乘,由于矩陣的乘法是不滿足乘法交換律的玷坠,所以變換操作的執(zhí)行順序是對(duì)結(jié)果有影響的蜗搔,繼續(xù)來(lái)個(gè)小Demo:

先平移,再放大八堡,再旋轉(zhuǎn)

實(shí)現(xiàn)代碼:

            Matrix matrix = new Matrix();
            matrix.setTranslate(200, 200);
            matrix.postScale(2, 2);
            matrix.postRotate(20);
            canvas.drawBitmap(mBitmap, matrix, null);
先平移樟凄,再旋轉(zhuǎn),再放大

實(shí)現(xiàn)代碼:

            Matrix matrix = new Matrix();
            matrix.setTranslate(200, 200);
            matrix.preScale(2, 2);
            matrix.preRotate(20);
            canvas.drawBitmap(mBitmap, matrix, null);

簡(jiǎn)單粗暴可以這樣理解:Matrix操作是一系列的任務(wù)存放在一個(gè)隊(duì)列里兄渺,pre是把當(dāng)前任務(wù)插入隊(duì)列前缝龄,post是插入隊(duì)列后,set則是清空隊(duì)列所有任務(wù)挂谍,再入隊(duì)二拐。

這些看似很簡(jiǎn)單很基礎(chǔ)的東西卻恰恰是最重要的,它可以創(chuàng)造出很多東西凳兵,比如圖片的自由手勢(shì)縮放,微博上面的自定義貼紙企软,美圖秀秀里的相框拼接等效果都離不開它庐扫。

源碼下載:

這里附上源碼地址(歡迎Star,歡迎Fork):BeautyImageDemo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末仗哨,一起剝皮案震驚了整個(gè)濱河市形庭,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌厌漂,老刑警劉巖萨醒,帶你破解...
    沈念sama閱讀 221,198評(píng)論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異苇倡,居然都是意外死亡富纸,警方通過(guò)查閱死者的電腦和手機(jī)囤踩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評(píng)論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)晓褪,“玉大人堵漱,你說(shuō)我怎么就攤上這事』练拢” “怎么了勤庐?”我有些...
    開封第一講書人閱讀 167,643評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)好港。 經(jīng)常有香客問我愉镰,道長(zhǎng),這世上最難降的妖魔是什么钧汹? 我笑而不...
    開封第一講書人閱讀 59,495評(píng)論 1 296
  • 正文 為了忘掉前任丈探,我火速辦了婚禮,結(jié)果婚禮上崭孤,老公的妹妹穿的比我還像新娘类嗤。我一直安慰自己,他們只是感情好辨宠,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評(píng)論 6 397
  • 文/花漫 我一把揭開白布遗锣。 她就那樣靜靜地躺著,像睡著了一般嗤形。 火紅的嫁衣襯著肌膚如雪精偿。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評(píng)論 1 308
  • 那天赋兵,我揣著相機(jī)與錄音笔咽,去河邊找鬼。 笑死霹期,一個(gè)胖子當(dāng)著我的面吹牛叶组,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播历造,決...
    沈念sama閱讀 40,743評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼甩十,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了吭产?” 一聲冷哼從身側(cè)響起侣监,我...
    開封第一講書人閱讀 39,659評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎臣淤,沒想到半個(gè)月后橄霉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邑蒋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評(píng)論 3 340
  • 正文 我和宋清朗相戀三年姓蜂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了按厘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,424評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡覆糟,死狀恐怖刻剥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情滩字,我是刑警寧澤造虏,帶...
    沈念sama閱讀 36,107評(píng)論 5 349
  • 正文 年R本政府宣布,位于F島的核電站麦箍,受9級(jí)特大地震影響漓藕,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜挟裂,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評(píng)論 3 333
  • 文/蒙蒙 一享钞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧诀蓉,春花似錦栗竖、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評(píng)論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至沥曹,卻和暖如春份名,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背妓美。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評(píng)論 1 271
  • 我被黑心中介騙來(lái)泰國(guó)打工僵腺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人壶栋。 一個(gè)月前我還...
    沈念sama閱讀 48,798評(píng)論 3 376
  • 正文 我出身青樓辰如,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親贵试。 傳聞我的和親對(duì)象是個(gè)殘疾皇子琉兜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評(píng)論 2 359

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