2010年12月18日 星期六

幫圖片加上影像特效 - 負片與灰階效果

Create simple effects for your images (III) - Negative & Grayscale Effects
前兩次提過,簡單地利用 Matrix ,就可以輕易做出 陰影特效鏡像特效
這次,我將向大家分享,如何利用另一種 Matrix - ColorMatrix,來做出負片與灰階效果。
最上面那張圖的上半部,是原來的影像,一個美麗的地球。下半部的左邊,就是這地球影像的負片效果。右邊,則是灰階效果的呈現。
負片效果
負片效果的演算法,很簡單。就像底下這樣。
  1. R' = 255 - R;  
  2. G' = 255 - G;  
  3. B' = 255 - B;  
算法很簡單,可是在 Android 中要如何做到呢?難不成要用 Bitmap.getPixel()Bitmap.setPixel(),逐一針對每個像素來改他的顏色值?!
當然不是!這樣的做法,太沒效率,速度一定很慢。在 Android 中,針對這樣的需求,你可以透過 ColorMatrixColorFilter 來完成。在建構一個 ColorMatrixColorFilter 時,你得傳給他一個 ColorMatrix。因此,重點就在這個 ColorMatrix。
ColorMatrix 文件一開頭的註釋,就已經將他的功能講得很清楚。
  1. //5x4 matrix for transforming the color+alpha components of a Bitmap.  
  2. //The matrix is stored in a single array, and its treated as follows:  
  3. //[ a, b, c, d, e,  
  4. //  f, g, h, i, j,  
  5. //  k, l, m, n, o,  
  6. //  p, q, r, s, t ]  
  7. //  
  8. //When applied to a color [r, g, b, a], the resulting color is computed as  
  9. //(after clamping)  
  10. // R' = a*R + b*G + c*B + d*A + e;  
  11. // G' = f*R + g*G + h*B + i*A + j;  
  12. // B' = k*R + l*G + m*B + n*A + o;  
  13. // A' = p*R + q*G + r*B + s*A + t;  
讓我們看一下,這負片效果的原始碼,你會更加清楚。
  1. Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);    
  2. ColorMatrix cm = new ColorMatrix(new float[] {  
  3.   -1f,  0f,  0f, 0f, 255f,  
  4.    0f, -1f,  0f, 0f, 255f,  
  5.    0f,  0f, -1f, 0f, 255f,  
  6.    0f,  0f,  0f, 1f,   0f});  
  7. paint.setColorFilter(new ColorMatrixColorFilter(cm));  
  8. canvas.drawBitmap(m_bmp, 00, paint);  
將一個地球的圖片設給 m_bmp,透過上面這個程式範例,畫出來的樣子,就是一張具有負片效果的圖。
灰階效果
負片會了,灰階應該也很簡單了吧!我告訴你,要完成灰階效果,更簡單。ColorMatrix 都幫你將算法寫好了。你只要呼叫 ColorMatrix.setSaturation(0) 即可。
等等,學東西,可不能這樣就含混帶過。別忘了,Android 的原始碼都給你了,我們得利用他追根究柢,一探究竟才行。
打開 ColorMatrix.java 的原始碼,翻到 setSaturation()。這個函式的實現如下:
  1. public void setSaturation(float sat) {  
  2.   reset();  
  3.   float[] m = mArray;  
  4.   
  5.   final float invSat = 1 - sat;  
  6.   final float R = 0.213f * invSat;  
  7.   final float G = 0.715f * invSat;  
  8.   final float B = 0.072f * invSat;  
  9.   
  10.   m[0] = R + sat; m[1] = G;       m[2] = B;  
  11.   m[5] = R;       m[6] = G + sat; m[7] = B;  
  12.   m[10] = R;      m[11] = G;      m[12] = B + sat;  
  13. }  
透過 android.graphics.ColorFilter 與 android.graphics.ColorMatrix,你還可以玩出更多的效果,別忘了 ApiDemos 的範例程式中,也有用到。
很多好東西,就在你身旁,千萬別捨近求遠了。

資料來源:
http://ysl-paradise.blogspot.com/2010/01/iii.html

沒有留言:

張貼留言