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

 

一、图片处理层:

package com.jacp.tone.view;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

import com.jacp.tone.R;

/**
 * 图片调色处理
 * @author
 *
 */
public class ToneLayer {
 
 /**
  * 饱和度标识
  */
 public static final int FLAG_SATURATION = 0x0;
 
 /**
  * 亮度标识
  */
 public static final int FLAG_LUM = 0x1;
 
 /**
  * 色相标识
  */
 public static final int FLAG_HUE = 0x2;
 
 /**
  * 饱和度
  */
 private TextView mSaturation;
 private SeekBar mSaturationBar;

 /**
  * 色相
  */
 private TextView mHue;
 private SeekBar mHueBar;

 /**
  * 亮度
  */
 private TextView mLum;
 private SeekBar mLumBar;

 private float mDensity;
 private static final int TEXT_WIDTH = 50;

 private LinearLayout mParent;

 private ColorMatrix mLightnessMatrix;
 private ColorMatrix mSaturationMatrix;
 private ColorMatrix mHueMatrix;
 private ColorMatrix mAllMatrix;

 /**
  * 亮度
  */
 private float mLumValue = 1F;

 /**
  * 饱和度
  */
 private float mSaturationValue = 0F;

 /**
  * 色相
  */
 private float mHueValue = 0F;
 
 /**
  * SeekBar的中间值
  */
 private static final int MIDDLE_VALUE = 127;
 
 /**
  * SeekBar的最大值
  */
 private static final int MAX_VALUE = 255;
 
 private ArrayList<SeekBar> mSeekBars = new ArrayList<SeekBar>();

 public ToneLayer(Context context) {
  init(context);
 }

 private void init(Context context) {
  mDensity = context.getResources().getDisplayMetrics().density;

  mSaturation = new TextView(context);
  mSaturation.setText(R.string.saturation);
  mHue = new TextView(context);
  mHue.setText(R.string.contrast);
  mLum = new TextView(context);
  mLum.setText(R.string.lightness);
  
  mSaturationBar = new SeekBar(context);
  mHueBar = new SeekBar(context);
  mLumBar = new SeekBar(context);
  
  mSeekBars.add(mSaturationBar);
  mSeekBars.add(mHueBar);
  mSeekBars.add(mLumBar);
  
  for (int i = 0, size = mSeekBars.size(); i < size; i++) {
   SeekBar seekBar = mSeekBars.get(i);
   seekBar.setMax(MAX_VALUE);
   seekBar.setProgress(MIDDLE_VALUE);
   seekBar.setTag(i);
  }

  LinearLayout saturation = new LinearLayout(context);
  saturation.setOrientation(LinearLayout.HORIZONTAL);
  saturation.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

  LinearLayout.LayoutParams txtLayoutparams = new LinearLayout.LayoutParams((int) (TEXT_WIDTH * mDensity), LinearLayout.LayoutParams.MATCH_PARENT);
  mSaturation.setGravity(Gravity.CENTER);
  saturation.addView(mSaturation, txtLayoutparams);

  LinearLayout.LayoutParams seekLayoutparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
  saturation.addView(mSaturationBar, seekLayoutparams);

  LinearLayout hue = new LinearLayout(context);
  hue.setOrientation(LinearLayout.HORIZONTAL);
  hue.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

  mHue.setGravity(Gravity.CENTER);
  hue.addView(mHue, txtLayoutparams);
  hue.addView(mHueBar, seekLayoutparams);

  LinearLayout lum = new LinearLayout(context);
  lum.setOrientation(LinearLayout.HORIZONTAL);
  lum.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));

  mLum.setGravity(Gravity.CENTER);
  lum.addView(mLum, txtLayoutparams);
  lum.addView(mLumBar, seekLayoutparams);

  mParent = new LinearLayout(context);
  mParent.setOrientation(LinearLayout.VERTICAL);
  mParent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
  mParent.addView(saturation);
  mParent.addView(hue);
  mParent.addView(lum);
 }

 public View getParentView() {
  return mParent;
 }

 /**
  * 设置饱和度值
  * @param saturation
  */
 public void setSaturation(int saturation) {
  mSaturationValue = saturation * 1.0F / MIDDLE_VALUE;
 }

 /**
  * 设置色相值
  * @param hue
  */
 public void setHue(int hue) {
  mHueValue = hue * 1.0F / MIDDLE_VALUE;
 }

 /**
  * 设置亮度值
  * @param lum
  */
 public void setLum(int lum) {
  mLumValue = (lum - MIDDLE_VALUE) * 1.0F / MIDDLE_VALUE * 180;
 }

 public ArrayList<SeekBar> getSeekBars()
 {
  return mSeekBars;
 }

 /**
  *
  * @param flag
  *            比特位0 表示是否改变色相,比位1表示是否改变饱和度,比特位2表示是否改变明亮度
  */
 public Bitmap handleImage(Bitmap bm, int flag) {
  Bitmap bmp = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(),
    Bitmap.Config.ARGB_8888);
  // 创建一个相同尺寸的可变的位图区,用于绘制调色后的图片
  Canvas canvas = new Canvas(bmp); // 得到画笔对象
  Paint paint = new Paint(); // 新建paint
  paint.setAntiAlias(true); // 设置抗锯齿,也即是边缘做平滑处理
  if (null == mAllMatrix) {
   mAllMatrix = new ColorMatrix();
  }

  if (null == mLightnessMatrix) {
   mLightnessMatrix = new ColorMatrix(); // 用于颜色变换的矩阵,android位图颜色变化处理主要是靠该对象完成
  }

  if (null == mSaturationMatrix) {
   mSaturationMatrix = new ColorMatrix();
  }

  if (null == mHueMatrix) {
   mHueMatrix = new ColorMatrix();
  }

  switch (flag) {
  case FLAG_HUE: // 需要改变色相
   mHueMatrix.reset();
   mHueMatrix.setScale(mHueValue, mHueValue, mHueValue, 1); // 红、绿、蓝三分量按相同的比例,最后一个参数1表示透明度不做变化,此函数详细说明参考
   // // android
   // doc
   break;
  case FLAG_SATURATION: // 需要改变饱和度
   // saturation 饱和度值,最小可设为0,此时对应的是灰度图(也就是俗话的“黑白图”),
   // 为1表示饱和度不变,设置大于1,就显示过饱和
   mSaturationMatrix.reset();
   mSaturationMatrix.setSaturation(mSaturationValue);
   break;
  case FLAG_LUM: // 亮度
   // hueColor就是色轮旋转的角度,正值表示顺时针旋转,负值表示逆时针旋转
   mLightnessMatrix.reset(); // 设为默认值
   mLightnessMatrix.setRotate(0, mLumValue); // 控制让红色区在色轮上旋转的角度
   mLightnessMatrix.setRotate(1, mLumValue); // 控制让绿红色区在色轮上旋转的角度
   mLightnessMatrix.setRotate(2, mLumValue); // 控制让蓝色区在色轮上旋转的角度
   // 这里相当于改变的是全图的色相
   break;
  }
  mAllMatrix.reset();
  mAllMatrix.postConcat(mHueMatrix);
  mAllMatrix.postConcat(mSaturationMatrix); // 效果叠加
  mAllMatrix.postConcat(mLightnessMatrix); // 效果叠加

  paint.setColorFilter(new ColorMatrixColorFilter(mAllMatrix));// 设置颜色变换效果
  canvas.drawBitmap(bm, 0, 0, paint); // 将颜色变化后的图片输出到新创建的位图区
  // 返回新的位图,也即调色处理后的图片
  return bmp;
 }

}

二、主界面:

package com.jacp.tone;

import java.util.ArrayList;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;

import com.jacp.tone.view.ToneLayer;

/**
 * 启动的主界面
 * @author
 *
 */
public class ImageToneActivity extends Activity implements OnSeekBarChangeListener {
 private ToneLayer mToneLayer;
 private ImageView mImageView;
 private Bitmap mBitmap;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        init();
    }
   
    private void init()
    {
     mToneLayer = new ToneLayer(this);
       
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);
        mImageView = (ImageView) findViewById(R.id.img_view);
        mImageView.setImageBitmap(mBitmap);
        ((LinearLayout) findViewById(R.id.tone_view)).addView(mToneLayer.getParentView());
       
        ArrayList<SeekBar> seekBars = mToneLayer.getSeekBars();
        for (int i = 0, size = seekBars.size(); i < size; i++)
        {
         seekBars.get(i).setOnSeekBarChangeListener(this);
        }
    }

 @Override
 public void onProgressChanged(SeekBar seekBar, int progress,
   boolean fromUser) {
  int flag = (Integer) seekBar.getTag();
  switch (flag)
  {
  case ToneLayer.FLAG_SATURATION:
   mToneLayer.setSaturation(progress);
   break;
  case ToneLayer.FLAG_LUM:
   mToneLayer.setLum(progress);
   break;
  case ToneLayer.FLAG_HUE:
   mToneLayer.setHue(progress);
   break;
  }
  
  mImageView.setImageBitmap(mToneLayer.handleImage(mBitmap, flag));
 }

 @Override
 public void onStartTrackingTouch(SeekBar seekBar) {
  
 }

 @Override
 public void onStopTrackingTouch(SeekBar seekBar) {
  
 }
}

三、布局文件:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
   
 <LinearLayout
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" >
 
     <ImageView
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:id="@+id/img_view"
         android:layout_gravity="center"
         />
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:id="@+id/tone_view"
         />
 </LinearLayout>
</ScrollView>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值