Android模糊影像教程(1)

lum發表於2014-04-16

在Android中,我們可以實現很多很酷的處理圖片的效果。在2014年某次會議的講演《影像的魔力》中,我介紹了其中的一部分。其中的一項技術是如何模糊影像,示例程式碼是使用RenderScript實現的,因為在Android中沒有內建的可使用的簡單的API。在這個系列中,我們將著眼於RenderScript模糊技術和JAVA實現模糊功能。我們還將進行一些基準測試,以瞭解每種方案的執行情況,並探討獲取最佳效能的可行方法。

讓我們先從實現一個簡單的可以執行的例子開始,使用RenderScript!對於沒有使用過RenderScript的開發者來說,這是一個讓人心生恐懼的設想,因為RenderScript真的是很難,是不是?是的,的確是。不過它也有一些事情真的很簡單,而模糊影像就是其中之一。

對於不熟悉RenderScript的人來說,他是在API11中引入的,並且有一個compat庫,提供RenderScript給API8及以後的版本。它本質上是一個面向圖形的本地計算框架。RenderScript引擎在執行期會選擇最合適的處理器(CPU或者GPU核心,多核處理器間可以分解原子操作)來執行請求的操作。本地語法基於C99,與OpenCL, CUDA, and GLSL的API相似。

如果這聽起來很可怕,請稍等一下,因為我們正要簡化整個過程。因為它是一個框架,允許我們建立自定義的核心來實現過濾與處理,它內建了不少可以使用的核心,其中的一個允許我們模糊影像。

後面的例項程式碼基於API17及更高版本開發,我已經決定不使用compat庫,因為在本文寫作的時候,Android Studio還不支援。此外,我們使用的模糊核心在API17後才引入,所以有最小SDK版本為17的需求。

讓我們深入到一個簡單的例子,這裡有一個非常簡單的RelativeLayout,包含了一個ImageView,上層還有個TextView:

part1-168x300

我們想要做的效果是模糊ImageView內位於TextView顯示區域的影像,有效的模糊ImageView後的區域。我們最終使用的技術是拿到位於TextView區域的影像副本進行模糊,然後再將模糊後的副本設定為TextView的背景。

我刻意的設計了這種佈局,使影像顯示實際大小,並從螢幕的左上方開始。這樣讓隨後的位置計算簡單些,而且這裡討論的是模糊技術而不是影像定位的數學演算法。嘗試設定ImageView的屬性android:scaleType=”center”,就會發現定位出現錯亂。

此處有一個方法,它有3個引數,一個點陣圖(已在ImageView裡獲得),一個檢視(這是我們的TextView,但是該技術適用於任意的檢視型別,所以我們將在方法中進行支援),以及一個半徑用來控制模糊的程度。

我們要做的第一件事是建立一個新的點陣圖物件,用來儲存想要模糊的影像區域的副本。它的大小將會是我們檢視的尺寸(2-5行)。

現在我們將空的點陣圖包裝到畫布中,我們可以在上面繪圖(7行)。

接下來的步驟我稱為”快取剪下”,我們拷貝點陣圖中的處於檢視顯示區域內的那部分影像(9-10行)。

接下來我們必須做的事情是構建一個RenderScript物件上下文,在其中我們執行模糊操作(12行)。

RenderScript是一個本地環境,它在自己的記憶體空間內執行,所以我們不能簡單的傳遞點陣圖引用,我們需要在JAVA和RenderScript記憶體區域進行序列化。這使用了一個分配例項來完成,這是在RenderScript記憶體區域中建立和引用物件的方式,為我們的點陣圖建立一個分配會將點陣圖的內容拷貝的分配區域中(14-15行)。

現在我們建立一個 ScriptIntrinsicBlur例項,它建立合適的RenderScript模糊指令碼,並且是指令碼物件的Java介面,它讓我們能夠控制它。(17-18行)。

指令碼的輸入定義了我們需要執行模糊的點陣圖源(20行)。

現在我們設定半徑來控制模糊強度(22行)。

forEach方法執行模糊操作,引數代表了結果的輸出位置。我們將它寫回源分配地址以減少建立的物件數量(24行)。

現在模糊完成了,但是我們必須把模糊後的影像拷貝回JAVA記憶體區域(26行)。

最後將模糊後的點陣圖包裝到BitmapDrawable內,並設定為檢視的背景(28-29行)。

我們已經使用完RenderScript上下文,清理掉。這樣做也將自動刪除我們的分配(31行)。

這就是我們完整的基本模糊邏輯,但目前還不清楚什麼地方和什麼時候我們需要呼叫此方法。不幸的是關於這個問題不能簡單的進行回答,所以我們將在接下來的文章中討論。

平時我喜歡每篇文章都發布相關工作程式碼,但是在本例中,我們還沒達到有一個可執行的完整的端到端的示例的程度。我保證在接下來的文章中進行調整。

相關文章