• 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>  
  • 相关阅读:
    Java类、实例初始化的顺序
    Java中堆栈的区别
    int与Integer的区别(基本类型与复杂类型的对比)转
    JS中函数执行顺序的问题?
    springMVC --@RequestParam注解(后台控制器获取参数)
    如何安装request库
    流程图
    认识broken pipe
    postman动态使用url
    自定义一个List排序规则,然后对另一个List按照该规则排序
  • 原文地址:https://www.cnblogs.com/clarence/p/3838032.html
Copyright © 2020-2023  润新知