提取圖片主顏色及灰度圖
本文主要內容
- 提取圖片主顏色
- 灰度圖
- 總結
本文介紹兩種常用的圖象演算法,一種是提取圖片主顏色,另一種是灰度圖。提取照片主顏色,這個功能經常被用到,例如應用icon的顏色,如果是很淺的白色,那麼手機launcher上顯示的應用名就不能用白色了,以防止看不清文字。
灰度圖,介面看起來是灰白的,無彩色,有時候也需要這種圖片。
1、提取圖片主顏色
先上效果圖:

本人使用對一張藍色的圖片,提取主色值,最後將提取到的主顏色值當成整體背景顯示出來。
其實演算法實質比較簡單,就是算平均值,遍歷畫素點,將畫素點中所有的 red、green、blue 分量分別累加,最後求出平均的 red、green、blue 值,使用平均值構造一個新的顏色。
遍歷畫素點,可以跳著遍歷,比如每隔4個畫素點取一個值,因為相隔很近的畫素點其實非常類似,這樣可以減少一點工作量。其次,計算得到平均值以後,可以採取一些邊界檢查,防止得到的顏色過於豔麗。
public int getMainColor(Bitmap bitmap){ long start = System.currentTimeMillis(); int r = 0; if (bitmap == null) { return r; } int width = bitmap.getWidth(); int height = bitmap.getHeight(); Log.i("okunu", "width = " + width + " height = " + height); int[] pixels = new int[width * height]; int totalR = 0, totalG = 0, totalB = 0; int sampleColor = 0; int sampleCount = 0; int red = 0, green = 0, blue = 0; bitmap.getPixels(pixels, 0, width, 0, 0, width, height); Log.i("okunu", "pixels.length = " + pixels.length); for (int i = 0; i < height; i+=4) { int s = i * width; for (int j = 0; j < width; j+=4) { sampleColor = pixels[s + j]; red = Color.red(sampleColor); green = Color.green(sampleColor); blue = Color.blue(sampleColor); totalR += red; totalG += green; totalB += blue; sampleCount++; } } Log.i("okunu", "sampleCount = " + sampleCount); totalR = (int) Math.floor(totalR/sampleCount); totalG = (int) Math.floor(totalG/sampleCount); totalB = (int) Math.floor(totalB/sampleCount); r = Color.rgb(totalR, totalG, totalB); Log.i("okunu", "time = " + (System.currentTimeMillis() - start) ); return r; }
2、灰度圖
依舊先看效果圖:

藍色圖片的灰度圖如第二張圖上顯示所示。
一幅完整的影象,是由紅色、綠色、藍色三個通道組成的。紅色、綠色、藍色三個通道的縮覽圖都是以灰度顯示的。用不同的灰度色階來表示“ 紅,綠,藍”在影象中的比重。通道中的純白,代表了該色光在此處為最高亮度,亮度級別是255。如果一幅影象,三個通道值是一樣的,就是一張灰度圖
我們可以通過下面幾種方法,將其轉換為灰度:
1.浮點演算法:Gray=R 0.3+G 0.59+B*0.11
2.整數方法:Gray=(R 30+G 59+B*11)/100
3.移位方法:Gray =(R 76+G 151+B*28)>>8;
4.平均值法:Gray=(R+G+B)/3;
5.僅取綠色:Gray=G;
本文我們採用第一種演算法實現灰度圖。
public Bitmap getGrayBitmap(Bitmap bitmap){ Bitmap r = null; long start = System.currentTimeMillis(); if (bitmap == null) { return r; } int width = bitmap.getWidth(); int height = bitmap.getHeight(); Log.i("okunu", "width = " + width + " height = " + height); int[] pixels = new int[width * height]; int[] out = new int[width * height]; int sampleColor = 0; int red = 0, green = 0, blue = 0; bitmap.getPixels(pixels, 0, width, 0, 0, width, height); Log.i("okunu", "pixels.length = " + pixels.length); for (int i = 0; i < height; i+=1) { int s = i * width; for (int j = 0; j < width; j+=1) { sampleColor = pixels[s + j]; red = Color.red(sampleColor); green = Color.green(sampleColor); blue = Color.blue(sampleColor); int modifColor = (int) (red*0.3 + green*0.59 + blue*0.11); out[s + j] = Color.rgb(modifColor, modifColor, modifColor); } } r = Bitmap.createBitmap(out, width, height, Bitmap.Config.RGB_565); Log.i("okunu", "time = " + (System.currentTimeMillis() - start) ); return r; }
3、總結
雖然我們不是專業的圖象處理人員,但一些簡單的概念我們需要明白,學習這些簡單的概念就可以實現很專業的功能。ps 上各種神乎其技的影象處理,其實也就是一步步簡單的操作累積而成的,而這些簡單操作背後都是簡單的影象處理概念。