Android截屏對圖片做高斯模糊處理

這幾天項目中需要模仿一下iOS版本的微博菜單彈出界面,如下圖:

用微博的同學都知道這個效果吧瘤载,這篇文章先實現(xiàn)模糊效果,進入卖擅、退出動畫后面文章分析鸣奔;

一、說一下實現(xiàn)思路惩阶,很簡單的:

1挎狸、截圖:就是獲取我們app得截圖

獲取我們Activity得根view即DecorView,關于DecorView断楷,sdk里面是這么說明的:

Java代碼

Retrieve?the?top-level?window?decor?view?(containing?the?standard?window?frame/decorations?and?the?client's?content?inside?of?that),?which?can?be?added?as?a?window?to?the?window?manager.

就是說獲取最頂層的window锨匆,可以添加到window manager里面;

拿到view之后可以調用view的getDrawingCache方法獲取bitmap截圖冬筒;

2恐锣、對圖片做高斯模糊;

高斯模糊在Photoshop里面用的比較多舞痰,可以用來去痘痘土榴。

大致原理是:對指定像素和其周圍像素進行加權平均來得到最終結果,使用高斯分布作為濾波器匀奏。

這兒可以了解詳細的算法原理:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

二鞭衩、代碼實現(xiàn):

代碼比較簡單,我自己加了注釋貼出來了:

Java代碼

privatevoidapplyBlur()?{

View?view?=?getWindow().getDecorView();

view.setDrawingCacheEnabled(true);

view.buildDrawingCache(true);

/**

*?獲取當前窗口快照娃善,相當于截屏

*/

Bitmap?bmp1?=?view.getDrawingCache();

intheight?=?getOtherHeight();

/**

*?除去狀態(tài)欄和標題欄

*/

Bitmap?bmp2?=?Bitmap.createBitmap(bmp1,0,?height,bmp1.getWidth(),?bmp1.getHeight()?-?height);

blur(bmp2,?text);

}

@SuppressLint("NewApi")

privatevoidblur(Bitmap?bkg,?View?view)?{

longstartMs?=?System.currentTimeMillis();

floatscaleFactor?=8;//圖片縮放比例论衍;

floatradius?=20;//模糊程度

Bitmap?overlay?=?Bitmap.createBitmap(

(int)?(view.getMeasuredWidth()?/?scaleFactor),

(int)?(view.getMeasuredHeight()?/?scaleFactor),

Bitmap.Config.ARGB_8888);

Canvas?canvas?=newCanvas(overlay);

canvas.translate(-view.getLeft()?/?scaleFactor,?-view.getTop()/?scaleFactor);

canvas.scale(1/?scaleFactor,1/?scaleFactor);

Paint?paint?=newPaint();

paint.setFlags(Paint.FILTER_BITMAP_FLAG);

canvas.drawBitmap(bkg,0,0,?paint);

overlay?=?FastBlur.doBlur(overlay,?(int)?radius,true);

view.setBackground(newBitmapDrawable(getResources(),?overlay));

/**

*?打印高斯模糊處理時間,如果時間大約16ms聚磺,用戶就能感到到卡頓坯台,時間越長卡頓越明顯,如果對模糊完圖片要求不高瘫寝,可是將scaleFactor設置大一些蜒蕾。

*/

Log.i("jerome","blur?time:"+?(System.currentTimeMillis()?-?startMs));

}

/**

*?獲取系統(tǒng)狀態(tài)欄和軟件標題欄稠炬,部分軟件沒有標題欄,看自己軟件的配置咪啡;

*?@return

*/

privateintgetOtherHeight()?{

Rect?frame?=newRect();

getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);

intstatusBarHeight?=?frame.top;

intcontentTop?=?getWindow().findViewById(Window.ID_ANDROID_CONTENT).getTop();

inttitleBarHeight?=?contentTop?-?statusBarHeight;

returnstatusBarHeight?+?titleBarHeight;

}

我這里用了外國開源項目中的一個Java算法首启,地址:https://github.com/paveldudka/blurring

Java代碼

packagecom.jerome.popdemo;

importandroid.graphics.Bitmap;

/**

*?Created?by?paveld?on?3/6/14.

*/

publicclassFastBlur?{

publicstaticBitmap?doBlur(Bitmap?sentBitmap,intradius,

booleancanReuseInBitmap)?{

Bitmap?bitmap;

if(canReuseInBitmap)?{

bitmap?=?sentBitmap;

}else{

bitmap?=?sentBitmap.copy(sentBitmap.getConfig(),true);

}

if(radius?<1)?{

return(null);

}

intw?=?bitmap.getWidth();

inth?=?bitmap.getHeight();

int[]?pix?=newint[w?*?h];

bitmap.getPixels(pix,0,?w,0,0,?w,?h);

intwm?=?w?-1;

inthm?=?h?-1;

intwh?=?w?*?h;

intdiv?=?radius?+?radius?+1;

intr[]?=newint[wh];

intg[]?=newint[wh];

intb[]?=newint[wh];

intrsum,?gsum,?bsum,?x,?y,?i,?p,?yp,?yi,?yw;

intvmin[]?=newint[Math.max(w,?h)];

intdivsum?=?(div?+1)?>>1;

divsum?*=?divsum;

intdv[]?=newint[256*?divsum];

for(i?=0;?i?<256*?divsum;?i++)?{

dv[i]?=?(i?/?divsum);

}

yw?=?yi?=0;

int[][]?stack?=newint[div][3];

intstackpointer;

intstackstart;

int[]?sir;

intrbs;

intr1?=?radius?+1;

introutsum,?goutsum,?boutsum;

intrinsum,?ginsum,?binsum;

for(y?=0;?y?<?h;?y++)?{

rinsum?=?ginsum?=?binsum?=?routsum?=?goutsum?=?boutsum?=?rsum?=?gsum?=?bsum?=0;

for(i?=?-radius;?i?<=?radius;?i++)?{

p?=?pix[yi?+?Math.min(wm,?Math.max(i,0))];

sir?=?stack[i?+?radius];

sir[0]?=?(p?&0xff0000)?>>16;

sir[1]?=?(p?&0x00ff00)?>>8;

sir[2]?=?(p?&0x0000ff);

rbs?=?r1?-?Math.abs(i);

rsum?+=?sir[0]?*?rbs;

gsum?+=?sir[1]?*?rbs;

bsum?+=?sir[2]?*?rbs;

if(i?>0)?{

rinsum?+=?sir[0];

ginsum?+=?sir[1];

binsum?+=?sir[2];

}else{

routsum?+=?sir[0];

goutsum?+=?sir[1];

boutsum?+=?sir[2];

}

}

stackpointer?=?radius;

for(x?=0;?x?<?w;?x++)?{

r[yi]?=?dv[rsum];

g[yi]?=?dv[gsum];

b[yi]?=?dv[bsum];

rsum?-=?routsum;

gsum?-=?goutsum;

bsum?-=?boutsum;

stackstart?=?stackpointer?-?radius?+?div;

sir?=?stack[stackstart?%?div];

routsum?-=?sir[0];

goutsum?-=?sir[1];

boutsum?-=?sir[2];

if(y?==0)?{

vmin[x]?=?Math.min(x?+?radius?+1,?wm);

}

p?=?pix[yw?+?vmin[x]];

sir[0]?=?(p?&0xff0000)?>>16;

sir[1]?=?(p?&0x00ff00)?>>8;

sir[2]?=?(p?&0x0000ff);

rinsum?+=?sir[0];

ginsum?+=?sir[1];

binsum?+=?sir[2];

rsum?+=?rinsum;

gsum?+=?ginsum;

bsum?+=?binsum;

stackpointer?=?(stackpointer?+1)?%?div;

sir?=?stack[(stackpointer)?%?div];

routsum?+=?sir[0];

goutsum?+=?sir[1];

boutsum?+=?sir[2];

rinsum?-=?sir[0];

ginsum?-=?sir[1];

binsum?-=?sir[2];

yi++;

}

yw?+=?w;

}

for(x?=0;?x?<?w;?x++)?{

rinsum?=?ginsum?=?binsum?=?routsum?=?goutsum?=?boutsum?=?rsum?=?gsum?=?bsum?=0;

yp?=?-radius?*?w;

for(i?=?-radius;?i?<=?radius;?i++)?{

yi?=?Math.max(0,?yp)?+?x;

sir?=?stack[i?+?radius];

sir[0]?=?r[yi];

sir[1]?=?g[yi];

sir[2]?=?b[yi];

rbs?=?r1?-?Math.abs(i);

rsum?+=?r[yi]?*?rbs;

gsum?+=?g[yi]?*?rbs;

bsum?+=?b[yi]?*?rbs;

if(i?>0)?{

rinsum?+=?sir[0];

ginsum?+=?sir[1];

binsum?+=?sir[2];

}else{

routsum?+=?sir[0];

goutsum?+=?sir[1];

boutsum?+=?sir[2];

}

if(i?<?hm)?{

yp?+=?w;

}

}

yi?=?x;

stackpointer?=?radius;

for(y?=0;?y?<?h;?y++)?{

//?Preserve?alpha?channel:?(?0xff000000?&?pix[yi]?)

pix[yi]?=?(0xff000000&?pix[yi])?|?(dv[rsum]?<<16)

|?(dv[gsum]?<<8)?|?dv[bsum];

rsum?-=?routsum;

gsum?-=?goutsum;

bsum?-=?boutsum;

stackstart?=?stackpointer?-?radius?+?div;

sir?=?stack[stackstart?%?div];

routsum?-=?sir[0];

goutsum?-=?sir[1];

boutsum?-=?sir[2];

if(x?==0)?{

vmin[y]?=?Math.min(y?+?r1,?hm)?*?w;

}

p?=?x?+?vmin[y];

sir[0]?=?r[p];

sir[1]?=?g[p];

sir[2]?=?b[p];

rinsum?+=?sir[0];

ginsum?+=?sir[1];

binsum?+=?sir[2];

rsum?+=?rinsum;

gsum?+=?ginsum;

bsum?+=?binsum;

stackpointer?=?(stackpointer?+1)?%?div;

sir?=?stack[stackpointer];

routsum?+=?sir[0];

goutsum?+=?sir[1];

boutsum?+=?sir[2];

rinsum?-=?sir[0];

ginsum?-=?sir[1];

binsum?-=?sir[2];

yi?+=?w;

}

}

bitmap.setPixels(pix,0,?w,0,0,?w,?h);

return(bitmap);

}

}

如果用C/C++實現(xiàn)jni調用,效果會高一些撤摸,可以參考:https://github.com/qiujuer/ImageBlurring/blob/master/README-ZH.md

Java代碼

/*************************************************

Copyright:??Copyright?QIUJUER?2013.

Author:?????Qiujuer

Date:???????2014-04-18

Description:實現(xiàn)圖片模糊處理

**************************************************/

#include

#define?ABS(a)?((a)<(0)?(-a):(a))

#define?MAX(a,b)?((a)>(b)?(a):(b))

#define?MIN(a,b)?((a)<(b)?(a):(b))

/*************************************************

Function:???????StackBlur(堆棧模糊)

Description:????使用堆棧方式進行圖片像素模糊處理

Calls:??????????malloc

Table?Accessed:?NULL

Table?Updated:??NULL

Input:??????????像素點集合毅桃,圖片寬,圖片高准夷,模糊半徑

Output:?????????返回模糊后的像素點集合

Return:?????????返回模糊后的像素點集合

Others:?????????NULL

*************************************************/

staticint*?StackBlur(int*?pix,intw,inth,intradius)?{

intwm?=?w?-1;

inthm?=?h?-1;

intwh?=?w?*?h;

intdiv?=?radius?+?radius?+1;

int*r?=?(int*)malloc(wh?*?sizeof(int));

int*g?=?(int*)malloc(wh?*?sizeof(int));

int*b?=?(int*)malloc(wh?*?sizeof(int));

intrsum,?gsum,?bsum,?x,?y,?i,?p,?yp,?yi,?yw;

int*vmin?=?(int*)malloc(MAX(w,h)?*?sizeof(int));

intdivsum?=?(div?+1)?>>1;

divsum?*=?divsum;

int*dv?=?(int*)malloc(256*?divsum?*?sizeof(int));

for(i?=0;?i?<256*?divsum;?i++)?{

dv[i]?=?(i?/?divsum);

}

yw?=?yi?=0;

int(*stack)[3]?=?(int(*)[3])malloc(div?*3*?sizeof(int));

intstackpointer;

intstackstart;

int*sir;

intrbs;

intr1?=?radius?+1;

introutsum,?goutsum,?boutsum;

intrinsum,?ginsum,?binsum;

for(y?=0;?y?<?h;?y++)?{

rinsum?=?ginsum?=?binsum?=?routsum?=?goutsum?=?boutsum?=?rsum?=?gsum?=?bsum?=0;

for(i?=?-radius;?i?<=?radius;?i++)?{

p?=?pix[yi?+?(MIN(wm,?MAX(i,0)))];

sir?=?stack[i?+?radius];

sir[0]?=?(p?&0xff0000)?>>16;

sir[1]?=?(p?&0x00ff00)?>>8;

sir[2]?=?(p?&0x0000ff);

rbs?=?r1?-?ABS(i);

rsum?+=?sir[0]?*?rbs;

gsum?+=?sir[1]?*?rbs;

bsum?+=?sir[2]?*?rbs;

if(i?>0)?{

rinsum?+=?sir[0];

ginsum?+=?sir[1];

binsum?+=?sir[2];

}

else{

routsum?+=?sir[0];

goutsum?+=?sir[1];

boutsum?+=?sir[2];

}

}

stackpointer?=?radius;

for(x?=0;?x?<?w;?x++)?{

r[yi]?=?dv[rsum];

g[yi]?=?dv[gsum];

b[yi]?=?dv[bsum];

rsum?-=?routsum;

gsum?-=?goutsum;

bsum?-=?boutsum;

stackstart?=?stackpointer?-?radius?+?div;

sir?=?stack[stackstart?%?div];

routsum?-=?sir[0];

goutsum?-=?sir[1];

boutsum?-=?sir[2];

if(y?==0)?{

vmin[x]?=?MIN(x?+?radius?+1,?wm);

}

p?=?pix[yw?+?vmin[x]];

sir[0]?=?(p?&0xff0000)?>>16;

sir[1]?=?(p?&0x00ff00)?>>8;

sir[2]?=?(p?&0x0000ff);

rinsum?+=?sir[0];

ginsum?+=?sir[1];

binsum?+=?sir[2];

rsum?+=?rinsum;

gsum?+=?ginsum;

bsum?+=?binsum;

stackpointer?=?(stackpointer?+1)?%?div;

sir?=?stack[(stackpointer)?%?div];

routsum?+=?sir[0];

goutsum?+=?sir[1];

boutsum?+=?sir[2];

rinsum?-=?sir[0];

ginsum?-=?sir[1];

binsum?-=?sir[2];

yi++;

}

yw?+=?w;

}

for(x?=0;?x?<?w;?x++)?{

rinsum?=?ginsum?=?binsum?=?routsum?=?goutsum?=?boutsum?=?rsum?=?gsum?=?bsum?=0;

yp?=?-radius?*?w;

for(i?=?-radius;?i?<=?radius;?i++)?{

yi?=?MAX(0,?yp)?+?x;

sir?=?stack[i?+?radius];

sir[0]?=?r[yi];

sir[1]?=?g[yi];

sir[2]?=?b[yi];

rbs?=?r1?-?ABS(i);

rsum?+=?r[yi]?*?rbs;

gsum?+=?g[yi]?*?rbs;

bsum?+=?b[yi]?*?rbs;

if(i?>0)?{

rinsum?+=?sir[0];

ginsum?+=?sir[1];

binsum?+=?sir[2];

}

else{

routsum?+=?sir[0];

goutsum?+=?sir[1];

boutsum?+=?sir[2];

}

if(i?<?hm)?{

yp?+=?w;

}

}

yi?=?x;

stackpointer?=?radius;

for(y?=0;?y?<?h;?y++)?{

//?Preserve?alpha?channel:?(?0xff000000?&?pix[yi]?)

pix[yi]?=?(0xff000000&?pix[yi])?|?(dv[rsum]?<<16)?|?(dv[gsum]?<<8)?|?dv[bsum];

rsum?-=?routsum;

gsum?-=?goutsum;

bsum?-=?boutsum;

stackstart?=?stackpointer?-?radius?+?div;

sir?=?stack[stackstart?%?div];

routsum?-=?sir[0];

goutsum?-=?sir[1];

boutsum?-=?sir[2];

if(x?==0)?{

vmin[y]?=?MIN(y?+?r1,?hm)?*?w;

}

p?=?x?+?vmin[y];

sir[0]?=?r[p];

sir[1]?=?g[p];

sir[2]?=?b[p];

rinsum?+=?sir[0];

ginsum?+=?sir[1];

binsum?+=?sir[2];

rsum?+=?rinsum;

gsum?+=?ginsum;

bsum?+=?binsum;

stackpointer?=?(stackpointer?+1)?%?div;

sir?=?stack[stackpointer];

routsum?+=?sir[0];

goutsum?+=?sir[1];

boutsum?+=?sir[2];

rinsum?-=?sir[0];

ginsum?-=?sir[1];

binsum?-=?sir[2];

yi?+=?w;

}

}

free(r);

free(g);

free(b);

free(vmin);

free(dv);

free(stack);

return(pix);

}

最后來一張屌絲做demo專業(yè)效果圖:

技術交流QQ群:364595326

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末钥飞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子衫嵌,更是在濱河造成了極大的恐慌读宙,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件楔绞,死亡現(xiàn)場離奇詭異结闸,居然都是意外死亡,警方通過查閱死者的電腦和手機墓律,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門膀估,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人耻讽,你說我怎么就攤上這事察纯。” “怎么了针肥?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵饼记,是天一觀的道長。 經常有香客問我慰枕,道長具则,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任具帮,我火速辦了婚禮博肋,結果婚禮上,老公的妹妹穿的比我還像新娘蜂厅。我一直安慰自己匪凡,他們只是感情好,可當我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布掘猿。 她就那樣靜靜地躺著病游,像睡著了一般。 火紅的嫁衣襯著肌膚如雪稠通。 梳的紋絲不亂的頭發(fā)上衬衬,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天买猖,我揣著相機與錄音,去河邊找鬼滋尉。 笑死玉控,一個胖子當著我的面吹牛,可吹牛的內容都是我干的兼砖。 我是一名探鬼主播奸远,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼讽挟!你這毒婦竟也來了?” 一聲冷哼從身側響起丸冕,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤耽梅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后胖烛,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體眼姐,經...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年佩番,在試婚紗的時候發(fā)現(xiàn)自己被綠了众旗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡趟畏,死狀恐怖贡歧,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情赋秀,我是刑警寧澤利朵,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站猎莲,受9級特大地震影響绍弟,放射性物質發(fā)生泄漏。R本人自食惡果不足惜著洼,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一樟遣、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧身笤,春花似錦豹悬、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至莹弊,卻和暖如春涤久,著一層夾襖步出監(jiān)牢的瞬間涡尘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工响迂, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留考抄,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓蔗彤,卻偏偏與公主長得像川梅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子然遏,可洞房花燭夜當晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內容

  • 上圖展示了一種很典型的視覺效果——文字的背景不再是固定的待侵,而是將底層的相應區(qū)域模糊化丢早,好似蓋了一層毛玻璃。 其原理...
    沉思的Panda閱讀 12,574評論 1 52
  • 背景 一年多以前我在知乎上答了有關LeetCode的問題, 分享了一些自己做題目的經驗秧倾。 張土汪:刷leetcod...
    土汪閱讀 12,744評論 0 33
  • 計算機二級C語言上機題庫(南開版) 1.m個人的成績存放在score數(shù)組中怨酝,請編寫函數(shù)fun,它的功能是:將低于平...
    MrSunbeam閱讀 6,366評論 1 42
  • 緣,是個很奇妙的事那先。但我相信农猬,若是有緣,我們一定會在陌生的人群中相遇售淡。 認識小餃子斤葱,是在美樂嬰的早教群里。一開始勋又,...
    陳蕾FZ閱讀 655評論 0 50
  • 化學物質在我的心臟部位集結苦掘,商討應對一些莫須有的大事!
    05e357f628f8閱讀 203評論 0 0