首页 > 代码库 > android图像处理系列之三--图片色调饱和度、色相、亮度处理

android图像处理系列之三--图片色调饱和度、色相、亮度处理

原图:

处理后:

下面贴代码:

一、图片处理层:

[java] view plaincopy
 
  1. package com.jacp.tone.view;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.content.Context;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.Canvas;  
  8. import android.graphics.ColorMatrix;  
  9. import android.graphics.ColorMatrixColorFilter;  
  10. import android.graphics.Paint;  
  11. import android.view.Gravity;  
  12. import android.view.View;  
  13. import android.widget.LinearLayout;  
  14. import android.widget.SeekBar;  
  15. import android.widget.SeekBar.OnSeekBarChangeListener;  
  16. import android.widget.TextView;  
  17.   
  18. import com.jacp.tone.R;  
  19.   
  20. /** 
  21.  * 图片调色处理 
  22.  * @author maylian7700@126.com 
  23.  * 
  24.  */  
  25. public class ToneLayer {  
  26.       
  27.     /** 
  28.      * 饱和度标识 
  29.      */  
  30.     public static final int FLAG_SATURATION = 0x0;  
  31.       
  32.     /** 
  33.      * 亮度标识 
  34.      */  
  35.     public static final int FLAG_LUM = 0x1;  
  36.       
  37.     /** 
  38.      * 色相标识 
  39.      */  
  40.     public static final int FLAG_HUE = 0x2;  
  41.       
  42.     /** 
  43.      * 饱和度 
  44.      */  
  45.     private TextView mSaturation;  
  46.     private SeekBar mSaturationBar;  
  47.   
  48.     /** 
  49.      * 色相 
  50.      */  
  51.     private TextView mHue;  
  52.     private SeekBar mHueBar;  
  53.   
  54.     /** 
  55.      * 亮度 
  56.      */  
  57.     private TextView mLum;  
  58.     private SeekBar mLumBar;  
  59.   
  60.     private float mDensity;  
  61.     private static final int TEXT_WIDTH = 50;  
  62.   
  63.     private LinearLayout mParent;  
  64.   
  65.     private ColorMatrix mLightnessMatrix;  
  66.     private ColorMatrix mSaturationMatrix;  
  67.     private ColorMatrix mHueMatrix;  
  68.     private ColorMatrix mAllMatrix;  
  69.   
  70.     /** 
  71.      * 亮度 
  72.      */  
  73.     private float mLumValue = 1F;  
  74.   
  75.     /** 
  76.      * 饱和度 
  77.      */  
  78.     private float mSaturationValue = 0F;  
  79.   
  80.     /** 
  81.      * 色相 
  82.      */  
  83.     private float mHueValue = 0F;  
  84.       
  85.     /** 
  86.      * SeekBar的中间值 
  87.      */  
  88.     private static final int MIDDLE_VALUE = 127;  
  89.       
  90.     /** 
  91.      * SeekBar的最大值 
  92.      */  
  93.     private static final int MAX_VALUE = 255;  
  94.       
  95.     private ArrayList<SeekBar> mSeekBars = new ArrayList<SeekBar>();  
  96.   
  97.     public ToneLayer(Context context) {  
  98.         init(context);  
  99.     }  
  100.   
  101.     private void init(Context context) {  
  102.         mDensity = context.getResources().getDisplayMetrics().density;  
  103.   
  104.         mSaturation = new TextView(context);  
  105.         mSaturation.setText(R.string.saturation);  
  106.         mHue = new TextView(context);  
  107.         mHue.setText(R.string.contrast);  
  108.         mLum = new TextView(context);  
  109.         mLum.setText(R.string.lightness);  
  110.           
  111.         mSaturationBar = new SeekBar(context);  
  112.         mHueBar = new SeekBar(context);  
  113.         mLumBar = new SeekBar(context);  
  114.           
  115.         mSeekBars.add(mSaturationBar);  
  116.         mSeekBars.add(mHueBar);  
  117.         mSeekBars.add(mLumBar);  
  118.           
  119.         for (int i = 0, size = mSeekBars.size(); i < size; i++) {  
  120.             SeekBar seekBar = mSeekBars.get(i);  
  121.             seekBar.setMax(MAX_VALUE);  
  122.             seekBar.setProgress(MIDDLE_VALUE);  
  123.             seekBar.setTag(i);  
  124.         }  
  125.   
  126.         LinearLayout saturation = new LinearLayout(context);  
  127.         saturation.setOrientation(LinearLayout.HORIZONTAL);  
  128.         saturation.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));  
  129.   
  130.         LinearLayout.LayoutParams txtLayoutparams = new LinearLayout.LayoutParams((int) (TEXT_WIDTH * mDensity), LinearLayout.LayoutParams.MATCH_PARENT);  
  131.         mSaturation.setGravity(Gravity.CENTER);  
  132.         saturation.addView(mSaturation, txtLayoutparams);  
  133.   
  134.         LinearLayout.LayoutParams seekLayoutparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);  
  135.         saturation.addView(mSaturationBar, seekLayoutparams);  
  136.   
  137.         LinearLayout hue = new LinearLayout(context);  
  138.         hue.setOrientation(LinearLayout.HORIZONTAL);  
  139.         hue.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));  
  140.   
  141.         mHue.setGravity(Gravity.CENTER);  
  142.         hue.addView(mHue, txtLayoutparams);  
  143.         hue.addView(mHueBar, seekLayoutparams);  
  144.   
  145.         LinearLayout lum = new LinearLayout(context);  
  146.         lum.setOrientation(LinearLayout.HORIZONTAL);  
  147.         lum.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));  
  148.   
  149.         mLum.setGravity(Gravity.CENTER);  
  150.         lum.addView(mLum, txtLayoutparams);  
  151.         lum.addView(mLumBar, seekLayoutparams);  
  152.   
  153.         mParent = new LinearLayout(context);  
  154.         mParent.setOrientation(LinearLayout.VERTICAL);  
  155.         mParent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));  
  156.         mParent.addView(saturation);  
  157.         mParent.addView(hue);  
  158.         mParent.addView(lum);  
  159.     }  
  160.   
  161.     public View getParentView() {  
  162.         return mParent;  
  163.     }  
  164.   
  165.     /** 
  166.      * 设置饱和度值 
  167.      * @param saturation 
  168.      */  
  169.     public void setSaturation(int saturation) {  
  170.         mSaturationValue = saturation * 1.0F / MIDDLE_VALUE;  
  171.     }  
  172.   
  173.     /** 
  174.      * 设置色相值 
  175.      * @param hue 
  176.      */  
  177.     public void setHue(int hue) {  
  178.         mHueValue = hue * 1.0F / MIDDLE_VALUE;  
  179.     }  
  180.   
  181.     /** 
  182.      * 设置亮度值 
  183.      * @param lum 
  184.      */  
  185.     public void setLum(int lum) {  
  186.         mLumValue = (lum - MIDDLE_VALUE) * 1.0F / MIDDLE_VALUE * 180;  
  187.     }  
  188.   
  189.     public ArrayList<SeekBar> getSeekBars()  
  190.     {  
  191.         return mSeekBars;  
  192.     }  
  193.   
  194.     /** 
  195.      *  
  196.      * @param flag 
  197.      *            比特位0 表示是否改变色相,比位1表示是否改变饱和度,比特位2表示是否改变明亮度 
  198.      */  
  199.     public Bitmap handleImage(Bitmap bm, int flag) {  
  200.         Bitmap bmp = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(),  
  201.                 Bitmap.Config.ARGB_8888);  
  202.         // 创建一个相同尺寸的可变的位图区,用于绘制调色后的图片  
  203.         Canvas canvas = new Canvas(bmp); // 得到画笔对象  
  204.         Paint paint = new Paint(); // 新建paint  
  205.         paint.setAntiAlias(true); // 设置抗锯齿,也即是边缘做平滑处理  
  206.         if (null == mAllMatrix) {  
  207.             mAllMatrix = new ColorMatrix();  
  208.         }  
  209.   
  210.         if (null == mLightnessMatrix) {  
  211.             mLightnessMatrix = new ColorMatrix(); // 用于颜色变换的矩阵,android位图颜色变化处理主要是靠该对象完成  
  212.         }  
  213.   
  214.         if (null == mSaturationMatrix) {  
  215.             mSaturationMatrix = new ColorMatrix();  
  216.         }  
  217.   
  218.         if (null == mHueMatrix) {  
  219.             mHueMatrix = new ColorMatrix();  
  220.         }  
  221.   
  222.         switch (flag) {  
  223.         case FLAG_HUE: // 需要改变色相  
  224.             mHueMatrix.reset();  
  225.             mHueMatrix.setScale(mHueValue, mHueValue, mHueValue, 1); // 红、绿、蓝三分量按相同的比例,最后一个参数1表示透明度不做变化,此函数详细说明参考  
  226.             // // android  
  227.             // doc  
  228.             break;  
  229.         case FLAG_SATURATION: // 需要改变饱和度  
  230.             // saturation 饱和度值,最小可设为0,此时对应的是灰度图(也就是俗话的“黑白图”),  
  231.             // 为1表示饱和度不变,设置大于1,就显示过饱和  
  232.             mSaturationMatrix.reset();  
  233.             mSaturationMatrix.setSaturation(mSaturationValue);  
  234.             break;  
  235.         case FLAG_LUM: // 亮度  
  236.             // hueColor就是色轮旋转的角度,正值表示顺时针旋转,负值表示逆时针旋转  
  237.             mLightnessMatrix.reset(); // 设为默认值  
  238.             mLightnessMatrix.setRotate(0, mLumValue); // 控制让红色区在色轮上旋转的角度  
  239.             mLightnessMatrix.setRotate(1, mLumValue); // 控制让绿红色区在色轮上旋转的角度  
  240.             mLightnessMatrix.setRotate(2, mLumValue); // 控制让蓝色区在色轮上旋转的角度  
  241.             // 这里相当于改变的是全图的色相  
  242.             break;  
  243.         }  
  244.         mAllMatrix.reset();  
  245.         mAllMatrix.postConcat(mHueMatrix);  
  246.         mAllMatrix.postConcat(mSaturationMatrix); // 效果叠加  
  247.         mAllMatrix.postConcat(mLightnessMatrix); // 效果叠加  
  248.   
  249.         paint.setColorFilter(new ColorMatrixColorFilter(mAllMatrix));// 设置颜色变换效果  
  250.         canvas.drawBitmap(bm, 0, 0, paint); // 将颜色变化后的图片输出到新创建的位图区  
  251.         // 返回新的位图,也即调色处理后的图片  
  252.         return bmp;  
  253.     }  
  254.   
  255. }  


二、主界面:

[java] view plaincopy
 
  1. package com.jacp.tone;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.Activity;  
  6. import android.graphics.Bitmap;  
  7. import android.graphics.BitmapFactory;  
  8. import android.os.Bundle;  
  9. import android.widget.ImageView;  
  10. import android.widget.LinearLayout;  
  11. import android.widget.SeekBar;  
  12. import android.widget.SeekBar.OnSeekBarChangeListener;  
  13.   
  14. import com.jacp.tone.view.ToneLayer;  
  15.   
  16. /** 
  17.  * 启动的主界面 
  18.  * @author maylian7700@126.com 
  19.  * 
  20.  */  
  21. public class ImageToneActivity extends Activity implements OnSeekBarChangeListener {  
  22.     private ToneLayer mToneLayer;  
  23.     private ImageView mImageView;  
  24.     private Bitmap mBitmap;  
  25.       
  26.     @Override  
  27.     public void onCreate(Bundle savedInstanceState) {  
  28.         super.onCreate(savedInstanceState);  
  29.         setContentView(R.layout.main);  
  30.           
  31.         init();  
  32.     }  
  33.       
  34.     private void init()  
  35.     {  
  36.         mToneLayer = new ToneLayer(this);  
  37.           
  38.         mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);  
  39.         mImageView = (ImageView) findViewById(R.id.img_view);  
  40.         mImageView.setImageBitmap(mBitmap);  
  41.         ((LinearLayout) findViewById(R.id.tone_view)).addView(mToneLayer.getParentView());  
  42.           
  43.         ArrayList<SeekBar> seekBars = mToneLayer.getSeekBars();  
  44.         for (int i = 0, size = seekBars.size(); i < size; i++)  
  45.         {  
  46.             seekBars.get(i).setOnSeekBarChangeListener(this);  
  47.         }  
  48.     }  
  49.   
  50.     @Override  
  51.     public void onProgressChanged(SeekBar seekBar, int progress,  
  52.             boolean fromUser) {  
  53.         int flag = (Integer) seekBar.getTag();  
  54.         switch (flag)  
  55.         {  
  56.         case ToneLayer.FLAG_SATURATION:  
  57.             mToneLayer.setSaturation(progress);  
  58.             break;  
  59.         case ToneLayer.FLAG_LUM:  
  60.             mToneLayer.setLum(progress);  
  61.             break;  
  62.         case ToneLayer.FLAG_HUE:  
  63.             mToneLayer.setHue(progress);  
  64.             break;  
  65.         }  
  66.           
  67.         mImageView.setImageBitmap(mToneLayer.handleImage(mBitmap, flag));  
  68.     }  
  69.   
  70.     @Override  
  71.     public void onStartTrackingTouch(SeekBar seekBar) {  
  72.           
  73.     }  
  74.   
  75.     @Override  
  76.     public void onStopTrackingTouch(SeekBar seekBar) {  
  77.           
  78.     }  
  79. }  


三、布局文件:

[java] view plaincopy
 
    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     android:layout_width="match_parent"  
    4.     android:layout_height="match_parent"  
    5.     >  
    6.       
    7.     <LinearLayout   
    8.         android:layout_width="match_parent"  
    9.         android:layout_height="match_parent"  
    10.         android:orientation="vertical" >  
    11.       
    12.         <ImageView  
    13.             android:layout_width="wrap_content"  
    14.             android:layout_height="wrap_content"  
    15.             android:layout_weight="1"  
    16.             android:id="@+id/img_view"  
    17.             android:layout_gravity="center"  
    18.             />  
    19.         <LinearLayout  
    20.             android:layout_width="match_parent"  
    21.             android:layout_height="wrap_content"  
    22.             android:id="@+id/tone_view"  
    23.             />  
    24.     </LinearLayout>  
    25. </ScrollView>