Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 淺談android中圖片處理之色彩特效處理ColorMatrix(三)

淺談android中圖片處理之色彩特效處理ColorMatrix(三)

編輯:關於Android編程

在android開發中對圖片處理很是頻繁,其中對圖片的顏色處理就是很常見的一種。我們經常看到一些類似美圖秀秀,美顏相機的app,為什麼那麼黑的人拍出來是確實那麼地白呢?長的那麼那個(丑)的人,用美顏相機拍出來的看起來也有那麼回事(拍出來就感覺挺漂亮)。就像網上有個段子,有錢的都去韓國了,沒錢都用ps了。韓國的就去整形,中國的就用ps.這些話雖然是調侃,但是從某種程度上來說像類似美圖秀秀,美顏相機app確實挺受大家歡迎。但是你是否曾想過它這種效果,它是怎麼實現的嗎?你是否曾想過它的原理是什麼嗎?所以我將和大家一同由淺入深結合一些實例從原理上講解一下如何實現圖片的美顏以及各種圖片風格實現。

  要想實現對圖片的顏色的處理,首先就必須要了解圖片的組成原理。圖片主要有兩種數據結構形式的圖片,一種是位圖,另一種是矢量圖,但是在大部分的時候我們接觸到的都是位圖。

 

——圖像的兩種分類:

——位圖

例子:單色位圖

256位圖

24位位圖

位圖圖像(bitmap),亦稱為點陣圖像或繪制圖像,是由稱作像素(圖片元素)的單個點組成的。這些點可以進行不同的排列和染色以構成圖樣。當放大位圖時,可以看見賴以構成整個圖像的無數單個方塊。擴大位圖尺寸的效果是增大單個像素,從而使線條和形狀顯得參差不齊。然而,如果從稍遠的位置觀看它,位圖圖像的顏色和形狀又顯得是連續的。常用的位圖處理軟件是Photoshop。

位圖的常見格式:png、jpg、bmp

——矢量圖

矢量圖,也稱為面向對象的圖像或繪圖圖像,在數學上定義為一系列由線連接的點。矢量文件中的圖形元素稱為對象。每個對象都是一個自成一體的實體,它具有顏色、形狀、輪廓、大小和屏幕位置等屬性。

矢量圖是根據幾何特性來繪制圖形,矢量可以是一個點或一條線,矢量圖只能靠軟件生成,文件占用內在空間較小,因為這種類型的圖像文件包含獨立的分離圖像,可以自由無限制的重新組合。它的特點是放大後圖像不會失真,和分辨率無關,適用於圖形設計、文字設計和一些標志設計、版式設計等。

矢量圖的常見格式:svg、ps

  大家都知道我們經常使用的圖片的數據結構是位圖---->Bitmap.它包含一張圖片的所有的數據信息。整個圖片是由點陣和顏色值(ARGB)組成的。因為位圖是由像素點組成的,點陣指的是像素點的組成矩陣,而顏色值指的是;ARGB值,(A代表透明度,R代表紅色值,G代表綠色值,B則代表藍色)正好是自然界的三原色和透明度。大家都知道任何一種的顏色都可以使用三原色按照不同比例混合搭配而得到。所以這樣就造成了每張圖片都是色彩鮮艷,美觀好看。一張色彩鮮艷的圖片組成是這樣的,我們知道圖片是位圖(這裡不考慮矢量圖),都是很多個像素點矩陣組成,實際上每個像素點的ARGB都是不一樣的,也可以這麼說每個像素點的顏色都不一樣,然後不同顏色的像素點組成在一起就形成了一張色彩鮮艷圖片。

 前面我們多次提到了顏色矩陣,那麼我們就推出這次主角ColorMatrix顏色矩陣。

顏色矩陣的分析如下:

在Android中我們使用ColorMatrix矩陣來處理圖片的色彩的效果,Android的為顏色矩陣是一個4X5的數字矩陣,它用來對圖片色彩的處理。而對於每個像素點

都會有一個顏色的分量矩陣用來保存的ARGB值。注意:在android中使用的是一維數組來保存這個M矩陣(顏色矩陣)[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t]而C就是顏色分量矩陣

相信學了線性代數的都知道是通過矩陣乘法來對顏色分量矩陣

\

由以上的公式可以得出每個像素點的顏色分量矩陣,通過矩陣乘法得到:

R1=a*R+b*G+c*B+d*A+e;

G1=f*R+g*G+h*B+i*A+j;

B1=k*R+l*G+m*B+n*A+o;

A1=p*R+q*G+r*B+s*A+t;

通過以上公式的分析可得到,R1,G1,B1,A1分量值取決於他們的系數和最後加部分的偏移量(e,j,o,t).可得出如下結論:

1、第一行的a,b,c,d,e用來決定新的顏色值中的R的值(紅色)---a,b,c,d為系數,e則為偏移量(offset),若a=1;b,c,d都為0,e為任意值(0-N),這就可以的得到:R1=R+e(若e=0,則R1=R),那就得出了,影響單個紅色變化的有兩個因素:一個是系數a,另一個則是偏移量(offset)e.所以當我們想控制單個紅色的值話就可以從控制這兩個變量值即可。a的系數取值范圍為(-1 到 2之間),e為偏移量,當我的a系數定了後,其他的b,c,d參數為0,當修改e的值後就會改變紅色這個單個顏色的深淺程度,可以這樣理解前面幾個系數(a,b,c,d)用來配色的,而e後面偏移量則是用來控制顏色整體的深淺程度的

2、第二行f,g,h,i,j用來決定新的顏色值中的G的值(綠色)---f,g,h,i,j為系數,j則為偏移量(offset),若f=1;g,h,i都為0,j為任意值(0-N),這就可以的得到:G1=G+j(若j=0,則G1=G),那就得出了,影響單個綠色變化的有兩個因素:一個是系數f,另一個則是偏移量(offset)j.所以當我們想控制單個綠色的值話就可以從控制這兩個變量值即可。f的系數取值范圍為(0到 2之間),j為偏移量,當我的f系數定了後,其他的g,h,i參數為0,當修改j的值後就會改變綠色這個單個顏色的深淺程度,可以這樣理解前面幾個系數(f,g,h,i)用來配色的,而j後面偏移量則是用來控制顏色整體的深淺程度的

3、第三行的k,l,m,n,o用來決定新的顏色值中的B的值(藍色)---k,l,m,n為系數o則為偏移量(offset),若k=1;l,m,n都為0,o為任意值(0-N),這就可以的得到:B1=B+o(若o=0,則B1=B),那就得出了,影響單個藍色變化的有兩個因素:一個是系數k,另一個則是偏移量(offset)o.所以當我們想控制單個藍色的值話就可以從控制這兩個變量值即可。k的系數取值范圍為(0到 2之間),o為偏移量,當我的k系數定了後,其他的l,m,n參數為0,當修改o的值後就會改變藍色這個單個顏色的深淺程度,可以這樣理解前面幾個系數(k,l,m,n)用來配色的,而o後面偏移量則是用來控制顏色整體的深淺程度的

4、第四行的p,q,r,s,t用來決定新的顏色值中的A的值(透明度)---p,q,r,s為系數,t則為偏移量(offset),若p=1;q,r,s都為0,t為任意值(0-N),這就可以的得到:A1=A+t(若t=0,則A1=A),那就得出了,影響單個透明度變化的有兩個因素:一個是系數p,另一個則是偏移量(offset)t.所以當我們想控制單個透明度的值話就可以從控制這兩個變量值即可。a的系數取值范圍為(0 到 2之間),t為偏移量.

知道以上的各個參數的意思,那麼接下來我們就可以寫一個簡單的demo來實驗一下了。

 

package com.mikyou.imagecolor;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;


public class MainActivity extends Activity implements OnSeekBarChangeListener{
	private ImageView iv;
	private SeekBar redBar,greenBar,blueBar,alphaBar;
	private Canvas canvas;
	private Bitmap copyBitmap;
	private Bitmap baseBitmap;
	private Paint paint;
	private float redValue,greenValue,blueValue,alphaValue;//這些值都是通過SeekBar移動過程中而得到的變化的值
	//定義一個顏色矩陣,主要通過第一種方式改變顏色系數,來達到修改圖片的顏色。
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();

	}

	private void initView() {
		iv=(ImageView) findViewById(R.id.iv);		
		redBar=(SeekBar) findViewById(R.id.red);
		greenBar=(SeekBar) findViewById(R.id.green);
		blueBar=(SeekBar) findViewById(R.id.blue);
		alphaBar=(SeekBar) findViewById(R.id.alpha);
		redBar.setOnSeekBarChangeListener(this);
		greenBar.setOnSeekBarChangeListener(this);
		blueBar.setOnSeekBarChangeListener(this);
		alphaBar.setOnSeekBarChangeListener(this);
	}
	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromUser) {
		if (fromUser) {
			float count=seekBar.getProgress()/50f;//因為使得拖動條的取值為0f-2f,符合矩陣中每個元素的取值
			switch (seekBar.getId()) {
			case R.id.red:
				this.redValue=count;
				break;
			case R.id.green:
				this.greenValue=count;
				break;
			case R.id.blue:
				this.blueValue=count;
				break;
			case R.id.alpha:
				this.alphaValue=count;
				break;
			default:
				break;
			}
			initBitmap();
		}
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {

	}
	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {

	}

	private void initBitmap() {
		//先加載出一張原圖(baseBitmap),然後復制出來新的圖片(copyBitmap)來,因為andorid不允許對原圖進行修改.
		baseBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.pre);	
		//既然是復制一張與原圖一模一樣的圖片那麼這張復制圖片的畫紙的寬度和高度以及分辨率都要與原圖一樣,copyBitmap就為一張與原圖相同尺寸分辨率的空白畫紙
		copyBitmap=Bitmap.createBitmap(baseBitmap.getWidth(), baseBitmap.getHeight(), baseBitmap.getConfig());
		canvas=new Canvas(copyBitmap);//將畫紙固定在畫布上
		paint=new Paint();//實例畫筆對象
		float[] colorArray=new float[]{
				redValue,0,0,0,0,
				0,greenValue,0,0,0,
				0,0,blueValue,0,0,
				0,0,0,alphaValue,0
		};
		ColorMatrix colorMatrix=new ColorMatrix(colorArray);//將保存的顏色矩陣的數組作為參數傳入
		ColorMatrixColorFilter colorFilter=new ColorMatrixColorFilter(colorMatrix);//再把該colorMatrix作為參數傳入來實例化ColorMatrixColorFilter
		paint.setColorFilter(colorFilter);//並把該過濾器設置給畫筆
		canvas.drawBitmap(baseBitmap, new Matrix(), paint);//傳如baseBitmap表示按照原圖樣式開始繪制,將得到是復制後的圖片
		iv.setImageBitmap(copyBitmap);
	}
}

運行結果:

 

\\\\

以上方式就是通過第一種改變顏色系數方式來改變顏色,那麼接下來通過些簡單修改代碼,通過他們各個顏色的偏移量來修改顏色。

 

package com.mikyou.imagecolor;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;


public class MainActivity extends Activity implements OnSeekBarChangeListener{
	private ImageView iv;
	private SeekBar redBar,greenBar,blueBar,alphaBar;
	private Canvas canvas;
	private Bitmap copyBitmap;
	private Bitmap baseBitmap;
	private Paint paint;
	private float redValueOffset,greenValueOffset,blueValueOffset,alphaValueOffset;//這些值都是通過SeekBar移動過程中而得到的變化的值
	//定義一個顏色矩陣,主要通過第一種方式改變顏色系數,來達到修改圖片的顏色。
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();

	}

	private void initView() {
		iv=(ImageView) findViewById(R.id.iv);		
		redBar=(SeekBar) findViewById(R.id.red);
		greenBar=(SeekBar) findViewById(R.id.green);
		blueBar=(SeekBar) findViewById(R.id.blue);
		alphaBar=(SeekBar) findViewById(R.id.alpha);
		redBar.setOnSeekBarChangeListener(this);
		greenBar.setOnSeekBarChangeListener(this);
		blueBar.setOnSeekBarChangeListener(this);
		alphaBar.setOnSeekBarChangeListener(this);
	}
	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromUser) {
		if (fromUser) {
			float count=seekBar.getProgress();//因為使得拖動條的取值為0f-100f,符合矩陣中元素的偏移量取值
			switch (seekBar.getId()) {
			case R.id.red:
				this.redValueOffset=count;
				break;
			case R.id.green:
				this.greenValueOffset=count;
				break;
			case R.id.blue:
				this.blueValueOffset=count;
				break;
			case R.id.alpha:
				this.alphaValueOffset=count;
				break;
			default:
				break;
			}
			initBitmap();
		}
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {

	}
	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {

	}

	private void initBitmap() {
		//先加載出一張原圖(baseBitmap),然後復制出來新的圖片(copyBitmap)來,因為andorid不允許對原圖進行修改.
		baseBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.pre);	
		//既然是復制一張與原圖一模一樣的圖片那麼這張復制圖片的畫紙的寬度和高度以及分辨率都要與原圖一樣,copyBitmap就為一張與原圖相同尺寸分辨率的空白畫紙
		copyBitmap=Bitmap.createBitmap(baseBitmap.getWidth(), baseBitmap.getHeight(), baseBitmap.getConfig());
		canvas=new Canvas(copyBitmap);//將畫紙固定在畫布上
		paint=new Paint();//實例畫筆對象
		float[] colorArray=new float[]{
				1,0,0,0,redValueOffset,
				0,1,0,0,greenValueOffset,
				0,0,1,0,blueValueOffset,
				0,0,0,1,alphaValueOffset
		};
		ColorMatrix colorMatrix=new ColorMatrix(colorArray);//將保存的顏色矩陣的數組作為參數傳入
		ColorMatrixColorFilter colorFilter=new ColorMatrixColorFilter(colorMatrix);//再把該colorMatrix作為參數傳入來實例化ColorMatrixColorFilter
		paint.setColorFilter(colorFilter);//並把該過濾器設置給畫筆
		canvas.drawBitmap(baseBitmap, new Matrix(), paint);//傳如baseBitmap表示按照原圖樣式開始繪制,將得到是復制後的圖片
		iv.setImageBitmap(copyBitmap);
	}
}

運行效果:

 

\\

\\

細心的人會發現第二種方式和第一種是不一樣的。第二種在原圖基礎上修改顏色的偏移量。而第一種要達到原圖效果都得通過三種顏色搭配出來,所以第一種更加靈活。而第二種就更像我用手機拍了一張圖片在基礎上修改圖片風格。

其實,除了自己去修改那個顏色矩陣外,android官方還給出一些調整圖片的色光屬性封裝的API,主要用於修改色調(setRotate)、飽和度(setSaturation)、亮度(setScale)

1、修改色調的API(setRotate)

colorMatrix.setRotate(axis, degrees);//第一參數可傳入:0,1,2(0,1,2分別代表red,green,blue三種顏色的處理),第二個就是需要處理的值

    colorMatrix.setRotate(0, redValueOffset);//0代表紅色,redValueOffset表示需要對紅色處理的值
colorMatrix.setRotate(1, greenValueOffset);//1代表綠色,greenValueOffset表示需要對綠色處理的值
colorMatrix.setRotate(2, blueValueOffset);//2代表藍色,blueValueOffset表示需要對藍色處理的值

2、修改色調API(setSaturation)注意:當飽和度的顏色變為0的時候圖片就變為灰色的圖片了

3、修改亮度的API(setScale)當三原色如果是以相同的比例混合的話,就會顯示出白色。系統也就是根據這些原理來修改一個圖像的亮度的。當亮度為0,圖像就變黑了。

4、然後還有一個很重要的API,可以使用postConcat()方法將矩陣作用效果混合在一起,從而形成疊加的效果

具體用用法我們也通過一個demo來說明:

 

package com.mikyou.imagecolor;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;


public class MainActivity extends Activity implements OnSeekBarChangeListener{
	private ImageView iv;
	private SeekBar colorBar,baoheBar,lightBar;
	private Canvas canvas;
	private Bitmap copyBitmap;
	private Bitmap baseBitmap;
	private Paint paint;
	private float colorValue,baoheValue,lightValue;//這些值都是通過SeekBar移動過程中而得到的變化的值
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
	}

	private void initView() {
		iv=(ImageView) findViewById(R.id.iv);		
		colorBar=(SeekBar) findViewById(R.id.color);
		baoheBar=(SeekBar) findViewById(R.id.baohe);
		lightBar=(SeekBar) findViewById(R.id.light);
		colorBar.setOnSeekBarChangeListener(this);
		baoheBar.setOnSeekBarChangeListener(this);
		lightBar.setOnSeekBarChangeListener(this);
	}
	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromUser) {
		if (fromUser) {
			float count=seekBar.getProgress()/50f;//因為使得拖動條的取值為0f-2f,符合矩陣中元素的偏移量取值
			switch (seekBar.getId()) {
			case R.id.color:
				this.colorValue=count;
				break;
			case R.id.baohe:
				this.baoheValue=count;
				break;
			case R.id.light:
				this.lightValue=count;
				break;
			default:
				break;
			}
			initBitmap();
		}
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {

	}
	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {

	}

	private void initBitmap() {
		//先加載出一張原圖(baseBitmap),然後復制出來新的圖片(copyBitmap)來,因為andorid不允許對原圖進行修改.
		baseBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.pre);	
		//既然是復制一張與原圖一模一樣的圖片那麼這張復制圖片的畫紙的寬度和高度以及分辨率都要與原圖一樣,copyBitmap就為一張與原圖相同尺寸分辨率的空白畫紙
		copyBitmap=Bitmap.createBitmap(baseBitmap.getWidth(), baseBitmap.getHeight(), baseBitmap.getConfig());
		canvas=new Canvas(copyBitmap);//將畫紙固定在畫布上
		paint=new Paint();//實例畫筆對象
		ColorMatrix mColorMatrix=new ColorMatrix();
		//設置色調
		mColorMatrix.setRotate(0, colorValue);
		mColorMatrix.setRotate(1, colorValue);
		mColorMatrix.setRotate(2, colorValue);
		//設置飽和度
		ColorMatrix mBaoheMatrix=new ColorMatrix();
		mBaoheMatrix.setSaturation(baoheValue);
		//設置亮度:		colorMatrix.setScale(rScale, gScale, bScale, aScale)//第一個參數表示:紅色第二個表示綠色,第三個表示藍色,第四個表示透明度
		//當三原色如果是以相同的比例混合的話,就會顯示出白色。系統也就是根據這些原理來修改一個圖像的亮度的。當亮度為0,圖像就變黑了。
		//所以他們比例一樣
		ColorMatrix mLightMatrix=new ColorMatrix();
		mLightMatrix.setScale(lightValue, lightValue, lightValue, 1);
		//再創建組合的ColorMatrix對象將上面三種ColorMatrix的效果混合在一起
		ColorMatrix mImageViewMatrix=new ColorMatrix();
		mImageViewMatrix.postConcat(mColorMatrix);
		mImageViewMatrix.postConcat(mBaoheMatrix);
		mImageViewMatrix.postConcat(mLightMatrix);
		
		ColorMatrixColorFilter colorFilter=new ColorMatrixColorFilter(mImageViewMatrix);//再把該mImageViewMatrix作為參數傳入來實例化ColorMatrixColorFilter
		paint.setColorFilter(colorFilter);//並把該過濾器設置給畫筆
		canvas.drawBitmap(baseBitmap, new Matrix(), paint);//傳如baseBitmap表示按照原圖樣式開始繪制,將得到是復制後的圖片
		iv.setImageBitmap(copyBitmap);
	}
}

運行效果:

 

\\

\

通過上面一系列的demo相信你應該對ColorMatrix有了一定的認識了吧,其實寫到這裡我們完全可以做一個類似美顏處理的APP,當然這只是一個整體的思路,中間還有很多的細節需要去完善。我們現在都知道改變顏色矩陣的系數就能達到一種意想不到的圖片風格,比如什麼溫暖色調,復古色調,浪漫色調等等。無非是每種色調的顏色矩陣的系數不一樣而已。

下面就給出常見的幾種色調的顏色矩陣,並附上相應的Demo圖

 

//幾種常見的顏色矩陣:
//1、灰度效果
/* private float[] colorArray=new float[]{
0.33f,0.59f,0.11f,0,0,
0.33f,0.59f,0.11f,0,0,
0.33f,0.59f,0.11f,0,0,
0,0,0,1,0

};*/

\

//2、圖片反轉效果
/*private float[] colorArray=new float[]{
-1,0,0,1,1,
0,-1,0,1,1,
0,0,-1,1,1,
0,0,0,1,0

};*/

\

//3\懷舊效果
/* private float[] colorArray=new float[]{
0.393f,0.769f,0.189f,0,0,
0.349f,0.686f,0.168f,0,0,
0.272f,0.543f,0.131f,0,0,
0,0,0,1,0

};*/

\

//4\去色效果
/* private float[] colorArray=new float[]{
1.5f,1.5f,1.5f,0,-1,
1.5f,1.5f,1.5f,0,-1,
1.5f,1.5f,1.5f,0,-1,
0,0,0,1,0

};*/

\

//5\高飽和度效果
private float[] colorArray=new float[]{
1.438f,-0.122f,-0.016f,0,-0.03f,
-0.062f,1.378f,-0.016f,0,0.05f,
-0.062f,-0.122f,1.483f,0,-0.02f,
0,0,0,1,0
};

 

\

其實,上面所講那些方法來修改一張圖片的顏色,其實還有一種更為精確的方式,那就是針對每個像素點進行分析,就是通過改變每個像素點的具體ARGB的值來達到整張圖片的顏色值修改的目的。但是需要注意我們還是不能在原圖上修改,必須通過復制一張原圖,然後在復制的圖上進行修改即可。

主要是通過原圖的bitmap中的一個getPiexs方法獲得一張圖片的所有像素點,然後將這些像素點保存在一個數組中,然後再去遍歷這個數組取出每一個像素點,並按一定算法修改他們的ARGB值,然後通過Color.argb(a, r, g, b);得到新的數組,最後把這個產生的新數組設置到我們的復制的Bitmap中,注意最後繪制的時候,是傳入復制的Bitmap對象

因為很容易理解,因為我把原圖的像素點的修改後ARGB值都設置給復制的Bitmap,這張圖其實也就確定了,只是還沒畫出來而已。

代碼如下:

 

package com.mikyou.imagecolor;

import android.R.integer;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;


public class MainActivity extends Activity{
	private ImageView iv;
	private Canvas canvas;
	private Bitmap copyBitmap;
	private Bitmap baseBitmap;
	private Paint paint;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
		initBitmap();
	}
	private void initView() {
		iv=(ImageView) findViewById(R.id.iv);		
	}
	private void initBitmap() {
		//先加載出一張原圖(baseBitmap),然後復制出來新的圖片(copyBitmap)來,因為andorid不允許對原圖進行修改.
		baseBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.pre);
		copyBitmap=handleImageByPiex(baseBitmap);
		canvas=new Canvas(copyBitmap);//將畫紙固定在畫布上
		paint=new Paint();//實例畫筆對象
		canvas.drawBitmap(copyBitmap, new Matrix(), paint);//傳如copyBitmap因為我已經取到了原圖的所有像素點,並把他們設置到copyBitmap中
		//所以現在只需要將他畫出即可
		iv.setImageBitmap(copyBitmap);
	}
	
	//通過針對控制每個像素點ARGB方式來實現顏色控制
	//主要是通過getPixels方法得到所有的像素點,
	//第一個參數是用於接收像素點的數組
	//第二個參數是寫入到數組中的第一個像素的下標
	//第三個參數是數組的中行間距
	//第四,五個表示讀取第一個像素的坐標(x,y)
	//第六、width表示從每一行中讀取中讀取的像素寬度
	//第七、height表示讀取的行數
	private Bitmap  handleImageByPiex(Bitmap baseBitmap2) {
		int width=baseBitmap2.getWidth();
		int height=baseBitmap2.getHeight();
		int color,r,g,b,a;
		int [] oldPixels=new int[width*height];
		int [] newPixels=new int[width*height];
		Bitmap myCopyBitmap=Bitmap.createBitmap(baseBitmap2.getWidth(), baseBitmap2.getHeight(), baseBitmap2.getConfig());
		baseBitmap2.getPixels(oldPixels, 0, width, 0, 0, width, height);
		//然後就去遍歷這個數組oldPixels,並取出每個像素,然後再取出每個像素的ARGB屬性,然後通過想修改ARGB屬性,得到新的像素點
		//並把新的像素點保存新的數組newPixels中
		for (int i = 0; i < width*height; i++) {
			color=oldPixels[i];//取出每一個像素點
			r=Color.red(color);//取出當前像素點的R值
			g=Color.green(color);//取出當前像素點的G值
			b=Color.blue(color);////取出當前像素點的B值
			a=Color.alpha(color);////取出當前像素點的A值
			//然後通過相應的算法,重新修改這些值,並把最後的每個像素點保存到新的數組中
			//不同的效果對應著不同的算法:
/*			//1、底片效果
			B.r=255-B.r;
			 * B.g=255-B.g;
			 * B.b=255-B.b;
			 * 
			r=255-r;
			g=255-g;
			b=255-b;
			if (r>255) {
				r=255;
			}else if (r<0) {
				r=0;
			}
			if (g>255) {
				g=255;
			}else if (g<0) {
				g=0;
			}
			if (b>255) {
				b=255;
			}else if (b<0) {
				b=0;
			}*/
			/*老照片效果*/
			r=(int)(0.393*r+0.769*g+0.189*b);
			g=(int)(0.349*r+0.686*g+0.168*b);
			b=(int)(0.272*r+0.534*g+0.131*b);
			newPixels[i]=Color.argb(a, r, g, b);
		}
		myCopyBitmap.setPixels(newPixels, 0, width, 0, 0, width, height);
		return myCopyBitmap;
	}
}

運行結果:

 

底片效果:

\

老照片效果:

\

最後有關圖片的色彩的處理就到了,其實學到這裡真的可以根據自己思維去寫一個有關美顏圖片的app

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved