經過調整像素點來改變圖片顏色

        在上一篇文章中,咱們學習了經過顏色矩陣的變換來實現圖片不一樣顏色效果。沒讀過的朋友能夠點擊下面的連接:html

http://www.cnblogs.com/fuly550871915/p/4883681.htmlandroid

       在本篇中,咱們將實現更加好玩的效果,好比老照片效果,浮雕效果等。canvas

 

1、基礎知識數組

     其實每一張圖片的一個像素點就是一個顏色值,它包含四個份量,分別是:紅,綠,藍,透明度。試想若是咱們可以遍歷一張圖片的每個像素點,而後提取出這四個份量,作相應的計算操做,而後再返回,是否是就實現顏色的改變。沒錯,經過像素點來改變顏色就是這個原理。app

    好比咱們常見的底片的效果,它是遍歷圖片全部的像素點後,對每個像素點(好比B點)作了下面的計算的:工具

 

    那麼你可能會問,這個公式是怎麼獲得呢?這是研究圖像處理的專家給出的,只要這樣子處理像素點,就會獲得一個底片效果。咱們沒必要管這個。也就是說只要咱們知道公式,就能夠實現不一樣的有意思的效果。順便再說兩種效果的公式吧。佈局

    老照片的效果計算公式:post

     浮雕效果(注意是前一個像素減去後一個像素再加上127,再賦給前一個):學習

      好了,就介紹這幾種效果吧。你或許還有疑問,怎麼遍歷像素點,並取出份量呢?其實Bitmp類和Colro類已經給咱們提供了這樣子的方法。咱們看下面的設置底片效果的方法,註釋寫的很詳細,你想知道的都在註釋中。以下:this

 1 /**
 2      * 將圖片轉換爲負片
 3      * @param bitmap 原來圖片
 4      * @return 新圖片
 5      */
 6     public static Bitmap ImgaeToNegative(Bitmap bitmap){
 7         //其實咱們得到寬和高就是圖片像素的寬和高
 8         //它們的乘積就是總共一張圖片擁有的像素點數
 9         int width = bitmap.getWidth();
10         int height = bitmap.getHeight();
11         
12         Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
13         
14         int[] oldPx = new int[width*height];//用來存儲舊的色素點的數組
15         int[] newPx = new int[width*height];//用來存儲新的像素點的數組
16         int color;//用來存儲原來顏色值
17         int r,g,b,a;//存儲顏色的四個份量:紅,綠,藍,透明度
18         
19         //該方法用來將圖片的像素寫入到oldPx中,咱們這樣子設置,就會獲取所有的像素點
20         //第一個參數爲寫入的數組,第二個參數爲讀取第一個的像素點的偏移量,通常設置爲0
21         //第三個參數爲寫入時,多少個像素點做爲一行,第三個和第四個參數爲讀取的起點座標
22         //第五個參數表示讀取的長度,第六個表示讀取的高度
23         bitmap.getPixels(oldPx, 0, width, 0, 0, width, height);
24         //下面用循環來處理每個像素點
25         for(int i =0;i<width*height;i++){
26             
27             color = oldPx[i];//獲取一個原來的像素點
28             r = Color.red(color);//獲取紅色份量,下同
29             g = Color.green(color);
30             b = Color.blue(color);
31             a = Color.alpha(color);
32             
33             //下面計算生成新的顏色份量
34             r = 255 -r;
35             g = 255 - g;
36             b = 255 - b;
37             
38             //下面主要保證r g b 的值都必須在0~255以內
39             if(r>255){
40                 r = 255;
41             }else if(r<0){
42                 r = 0;
43             }
44             if(g>255){
45                 g = 255;
46             }else if(g<0){
47                 g = 0;
48             }
49             if(b>255){
50                 b = 255;
51             }else if(b<0){
52                 b = 0;
53             }
54             
55             //下面合成新的像素點,並添加到newPx中
56             color = Color.argb(a, r, g, b);
57             newPx[i] = color;
58         }
59         
60         //而後重要的一步,爲bmp設置新顏色了,該方法中的參數意義與getPixels中的同樣
61         //無非是將newPx寫入到bmp中
62         bmp.setPixels(newPx, 0, width, 0, 0, width, height);
63         return bmp;
64     }

      從上面的代碼中,你學會了如何遍歷一個圖片的像素點以及如何取出顏色份量和合成新的顏色。其餘的將圖片變爲老照片和浮雕,都是相似的方法。就很少講了。那麼咱們能夠直接進入實戰了。

 

2、實戰

      好了,咱們仍舊在上一篇文章的基礎上寫代碼,下面實現第三個按鈕」調整色素「。首先編寫color.3xml,用來顯示調整後的圖片,以下:

 1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical">
 6  
 7  <LinearLayout 
 8      android:layout_width="match_parent"
 9      android:layout_height="0dp"
10      android:layout_weight="1"
11      android:orientation="horizontal">
12      <ImageView 
13          android:id="@+id/img1"
14          android:layout_width="0dp"
15          android:layout_height="match_parent"
16          android:layout_weight="1"/>
17       <ImageView 
18          android:id="@+id/img2"
19          android:layout_width="0dp"
20          android:layout_height="match_parent"
21          android:layout_weight="1"/>
22     
23  </LinearLayout>
24  
25  <LinearLayout 
26      android:layout_width="match_parent"
27      android:layout_height="0dp"
28      android:layout_weight="1"
29      android:orientation="horizontal">
30         <ImageView 
31          android:id="@+id/img3"
32          android:layout_width="0dp"
33         android:layout_height="match_parent"
34          android:layout_weight="1"/>
35       <ImageView 
36          android:id="@+id/img4"
37          android:layout_width="0dp"
38           android:layout_height="match_parent"
39          android:layout_weight="1"/>
40     
41     
42  </LinearLayout>
43  
44  
45    
46 
47 </LinearLayout>

      在這個佈局中,咱們放置了四個ImageView,用來顯示原圖,底片,老照片以及浮雕效果。

     而後要擴充咱們的ImageHelper工具類了,將底片,老照片和浮雕實現的方法添加進去。代碼以下,註釋很詳細,建議仔細研讀。

  1 package com.fuly.image;
  2 
  3 import android.graphics.Bitmap;
  4 import android.graphics.Canvas;
  5 import android.graphics.Color;
  6 import android.graphics.ColorMatrix;
  7 import android.graphics.ColorMatrixColorFilter;
  8 import android.graphics.Paint;
  9 
 10 /*
 11  * 用來處理圖片顏色的工具類
 12  */
 13 public class ImageHelper {
 14     
 15     /**
 16      * 該方法根據色光三原色,改變圖片顏色
 17      * @param bmp 原圖片
 18      * @param huge 色相
 19      * @param saturation 飽和度
 20      * @param lum 亮度
 21      * @return
 22      */
 23     public static Bitmap ImageUtil(Bitmap bmp,float huge,float saturation,float lum){
 24         //注意,android不容許在原有的bitmap上操做,所以咱們必須重畫一個btimap來保存咱們所作的操做並返回
 25         //第三個參數爲制定顏色模式,一般會使用bitmap的最高處理方式
 26         Bitmap btp = Bitmap.createBitmap(bmp.getWidth(), bmp.getHeight(), Bitmap.Config.ARGB_8888);
 27         
 28         Canvas canvas = new Canvas(btp);//實例化一塊畫布
 29         Paint mPaint = new Paint();//實例化一支畫筆
 30         mPaint.setStrokeWidth(Paint.ANTI_ALIAS_FLAG);//設置爲抗鋸齒
 31         
 32         //實例化處理色相的顏色矩陣
 33         ColorMatrix hugeMatrix = new ColorMatrix();
 34         hugeMatrix.setRotate(0, huge);//0表示紅色
 35         hugeMatrix.setRotate(1, huge);//1表示設置綠色
 36         hugeMatrix.setRotate(2, huge);//2表示藍色
 37         
 38         //實例化處理飽和度的矩陣
 39         ColorMatrix satMatrix = new ColorMatrix();
 40         //查看該方法的源碼發現,只設置一個值方法內部就直接改變了每個三原色的飽和度
 41         satMatrix.setSaturation(saturation);
 42         
 43         //實例化處理亮度的矩陣
 44         ColorMatrix lumMatrix = new ColorMatrix();
 45         //參數從左到右依次爲紅色亮度,綠色,藍色,透明度(1表示徹底不透明)
 46         lumMatrix.setScale(lum, lum, lum, 1);
 47         
 48         //再實例化一個顏色矩陣將上面的顏色設定都柔和再一塊兒
 49         ColorMatrix imageMatrix = new ColorMatrix();
 50         imageMatrix.postConcat(hugeMatrix);
 51         imageMatrix.postConcat(satMatrix);
 52         imageMatrix.postConcat(lumMatrix);
 53         
 54         //將調好的顏色設置給畫筆
 55         mPaint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
 56         //而後咱們用調整好的顏色畫筆將原來的圖片bmp畫到新的bitmap上
 57         canvas.drawBitmap(bmp, 0, 0, mPaint);
 58         
 59         return btp;
 60         
 61     }
 62     /**
 63      * 將圖片轉換爲負片
 64      * @param bitmap 原來圖片
 65      * @return 新圖片
 66      */
 67     public static Bitmap ImgaeToNegative(Bitmap bitmap){
 68         //其實咱們得到寬和高就是圖片像素的寬和高
 69         //它們的乘積就是總共一張圖片擁有的像素點數
 70         int width = bitmap.getWidth();
 71         int height = bitmap.getHeight();
 72         
 73         Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
 74         
 75         int[] oldPx = new int[width*height];//用來存儲舊的色素點的數組
 76         int[] newPx = new int[width*height];//用來存儲新的像素點的數組
 77         int color;//用來存儲原來顏色值
 78         int r,g,b,a;//存儲顏色的四個份量:紅,綠,藍,透明度
 79         
 80         //該方法用來將圖片的像素寫入到oldPx中,咱們這樣子設置,就會獲取所有的像素點
 81         //第一個參數爲寫入的數組,第二個參數爲讀取第一個的像素點的偏移量,通常設置爲0
 82         //第三個參數爲寫入時,多少個像素點做爲一行,第三個和第四個參數爲讀取的起點座標
 83         //第五個參數表示讀取的長度,第六個表示讀取的高度
 84         bitmap.getPixels(oldPx, 0, width, 0, 0, width, height);
 85         //下面用循環來處理每個像素點
 86         for(int i =0;i<width*height;i++){
 87             
 88             color = oldPx[i];//獲取一個原來的像素點
 89             r = Color.red(color);//獲取紅色份量,下同
 90             g = Color.green(color);
 91             b = Color.blue(color);
 92             a = Color.alpha(color);
 93             
 94             //下面計算生成新的顏色份量
 95             r = 255 -r;
 96             g = 255 - g;
 97             b = 255 - b;
 98             
 99             //下面主要保證r g b 的值都必須在0~255以內
100             if(r>255){
101                 r = 255;
102             }else if(r<0){
103                 r = 0;
104             }
105             if(g>255){
106                 g = 255;
107             }else if(g<0){
108                 g = 0;
109             }
110             if(b>255){
111                 b = 255;
112             }else if(b<0){
113                 b = 0;
114             }
115             
116             //下面合成新的像素點,並添加到newPx中
117             color = Color.argb(a, r, g, b);
118             newPx[i] = color;
119         }
120         
121         //而後重要的一步,爲bmp設置新顏色了,該方法中的參數意義與getPixels中的同樣
122         //無非是將newPx寫入到bmp中
123         bmp.setPixels(newPx, 0, width, 0, 0, width, height);
124         return bmp;
125     }
126     /**
127      * 將圖片變成老照片
128      * @param bitmap 原來的圖片
129      * @return 新圖片(即老照片)
130      */
131     public static Bitmap ImgaeToOld(Bitmap bitmap){
132         
133         int width = bitmap.getWidth();
134         int height = bitmap.getHeight();
135         
136         Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
137         
138         int[] oldPx = new int[width*height];//用來存儲舊的色素點的數組
139         int[] newPx = new int[width*height];//用來存儲新的像素點的數組
140         int color;//用來存儲原來顏色值
141         int r,g,b,a;//存儲顏色的四個份量:紅,綠,藍,透明度
142         
143         //第一個參數爲寫入的數組,第二個參數爲讀取第一個的像素點的偏移量,通常設置爲0
144         //第三個參數爲寫入時,多少個像素點做爲一行,第三個和第四個參數爲讀取的起點座標
145         //第五個參數表示讀取的長度,第六個表示讀取的高度
146         bitmap.getPixels(oldPx, 0, width, 0, 0, width, height);
147         
148         for(int i =0;i<width*height;i++){
149             
150             color = oldPx[i];//獲取一個原來的像素點
151             r = Color.red(color);//獲取紅色份量,下同
152             g = Color.green(color);
153             b = Color.blue(color);
154             a = Color.alpha(color);
155             
156             //下面計算生成新的顏色份量
157             r = (int)(0.393*r+0.769*g+0.189*b);
158             g = (int)(0.349*r+0.686*g+0.168*b);
159             b = (int)(0.272*r+0.534*g+0.131*b);
160             
161             //下面主要保證r g b 的值都必須在0~255以內
162             if(r>255){
163                 r = 255;
164             }else if(r<0){
165                 r = 0;
166             }
167             if(g>255){
168                 g = 255;
169             }else if(g<0){
170                 g = 0;
171             }
172             if(b>255){
173                 b = 255;
174             }else if(b<0){
175                 b = 0;
176             }
177             
178             //下面合成新的像素點,並添加到newPx中
179             color = Color.argb(a, r, g, b);
180             newPx[i] = color;
181         }
182         
183         //而後重要的一步,爲bmp設置新顏色了
184         bmp.setPixels(newPx, 0, width, 0, 0, width, height);
185         return bmp;
186     }
187     /**
188      * 將圖片變成浮雕
189      * @param bitmap 舊照片
190      * @return 新照片
191      */
192     public static Bitmap ImgaeToRelief(Bitmap bitmap){
193         
194         int width = bitmap.getWidth();
195         int height = bitmap.getHeight();
196         
197         Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
198         
199         int[] oldPx = new int[width*height];//用來存儲舊的色素點的數組
200         int[] newPx = new int[width*height];//用來存儲新的像素點的數組
201         int color;//用來存儲前一個顏色值
202         int r,g,b,a;//存儲顏色的四個份量:紅,綠,藍,透明度
203         int color1;//用來存儲後一個顏色值
204         int r1,g1,b1,a1;
205         
206         //第一個參數爲寫入的數組,第二個參數爲讀取第一個的像素點的偏移量,通常設置爲0
207         //第三個參數爲寫入時,多少個像素點做爲一行,第三個和第四個參數爲讀取的起點座標
208         //第五個參數表示讀取的長度,第六個表示讀取的高度
209         bitmap.getPixels(oldPx, 0, width, 0, 0, width, height);
210         //注意是從1開始循環
211         for(int i =1;i<width*height;i++){
212             
213             color = oldPx[i-1];//獲取前一個像素點
214             r = Color.red(color);//獲取紅色份量,下同
215             g = Color.green(color);
216             b = Color.blue(color);
217             a = Color.alpha(color);
218             
219             color1 = oldPx[i];//獲取後一個像素點
220             r1 = Color.red(color1);//獲取紅色份量,下同
221             g1 = Color.green(color1);
222             b1 = Color.blue(color1);
223             a1 = Color.alpha(color1);
224             
225             //下面計算生成新的顏色份量,注意浮雕是前一個像素減去後一個像素再加上127,賦給前一個
226             r = r - r1 + 127;
227             g = g - g1 + 127;
228             b = b - b1 +127;
229             
230             //下面主要保證r g b 的值都必須在0~255以內
231             if(r>255){
232                 r = 255;
233             }else if(r<0){
234                 r = 0;
235             }
236             if(g>255){
237                 g = 255;
238             }else if(g<0){
239                 g = 0;
240             }
241             if(b>255){
242                 b = 255;
243             }else if(b<0){
244                 b = 0;
245             }
246             
247             //下面合成新的像素點,並添加到newPx中
248             color = Color.argb(a, r, g, b);
249             newPx[i] = color;
250         }
251         
252         //而後重要的一步,爲bmp設置新顏色了
253         bmp.setPixels(newPx, 0, width, 0, 0, width, height);
254         return bmp;
255     }
256     
257 }

        好了,咱們全部的工具方法都有了,下面就編寫」PxActivity「用來顯示這些效果吧。代碼以下:

 1 package com.fuly.image;
 2 
 3 import android.app.Activity;
 4 import android.graphics.Bitmap;
 5 import android.graphics.BitmapFactory;
 6 import android.graphics.drawable.BitmapDrawable;
 7 import android.os.Bundle;
 8 import android.widget.ImageView;
 9 
10 public class PxActivity extends Activity{
11     
12     private ImageView img1;
13     private ImageView img2;
14     private ImageView img3;
15     private ImageView img4;
16     
17     protected void onCreate(Bundle savedInstanceState) {
18         
19         super.onCreate(savedInstanceState);
20         setContentView(R.layout.color3);
21         img1 = (ImageView) findViewById(R.id.img1);
22         img2 = (ImageView) findViewById(R.id.img2);
23         img3 = (ImageView) findViewById(R.id.img3);
24         img4 = (ImageView) findViewById(R.id.img4);
25         
26         Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.test2);
27         
28         
29         img1.setImageBitmap(bmp);
30         img2.setImageBitmap(ImageHelper.ImgaeToNegative(bmp));
31         img3.setImageBitmap(ImageHelper.ImgaeToOld(bmp));
32         img4.setImageBitmap(ImageHelper.ImgaeToRelief(bmp));
33     }
34 
35 }

      代碼很簡單,無非就是調用咱們的工具類設置圖片而已。下面別忘記給這個活動註冊,而後給MainActivity中的按鈕註冊監聽,代碼以下:

 1 package com.fuly.image;
 2 
 3 import android.os.Bundle;
 4 import android.view.View;
 5 import android.widget.Button;
 6 import android.app.Activity;
 7 import android.content.Intent;
 8 
 9 public class MainActivity extends Activity {
10     
11     private Button btn1;
12 
13   
14     protected void onCreate(Bundle savedInstanceState) {
15         super.onCreate(savedInstanceState);
16         setContentView(R.layout.activity_main);
17         
18         btn1 = (Button) findViewById(R.id.bnt_imgcolor1);
19         
20     }
21 
22     /*
23      * btn1的點擊事件
24      */
25       public void preferenceClick(View view){
26           
27           Intent intent = new Intent(this,ColorAdjustActivity.class);
28           startActivity(intent);
29           
30           
31       }
32       /*
33        * btn2的點擊事件
34        */
35         public void matrixClick(View view){
36             
37             Intent intent = new Intent(this,ColorMatrixActivity.class);
38             startActivity(intent);
39            
40         }
41         /*
42          * btn3的點擊事件
43          */
44           public void pxClick(View view){
45               
46               Intent intent = new Intent(this,PxActivity.class);
47               startActivity(intent);
48              
49           }
50 
51   
52 }

       好了,全部代碼都完成了,運行程序,點擊」調整色素「按鈕,效果圖以下:

         其實這個三個按鈕均可以用了,咱們能夠爲所欲爲的實驗,看看效果了。至此,android中的圖像顏色處理就完結了,但願學習的的都能掌握。共同窗習,一塊兒進步!!

相關文章
相關標籤/搜索