R:红色 G:绿色 B:蓝色 A:透明度
- 色调/色相 : 物体传递的颜色
- 饱和度:颜色的纯度
- 亮度/明度:颜色的相对明暗程度
PS:可以用PS去试验一下对这个的理解会比较好。
Android中可以通过ColorMatrix类中的方法对色调/色相,饱和度以及亮度/明度进行调节,如下:
//色调
ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0,hue);//0为红色
hueMatrix.setRotate(1,hue);//1为绿色
hueMatrix.setRotate(2,hue);//2为蓝色
//饱和度
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);
//亮度
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum,lum,lum,1);
分装起来呢就是图像处理工具类:
package com.xjh.gin.image;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
/**
* Created by Gin on 2017/11/25.
*/
public class ImageHelper {
public static Bitmap handleImageEffect(Bitmap bm, float hue, float saturation, float lum) {//bm图像,hue色相,saturation饱和度,lum亮度
//传进来的bitmap是不能修改的
Bitmap bmp = Bitmap.createBitmap(bm.getWidth(),bm.getHeight(), Bitmap.Config.ARGB_8888);//最后一个是bitmap的处理方式
Canvas canvas = new Canvas(bmp);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);//抗锯齿
//色调
ColorMatrix hueMatrix = new ColorMatrix();
hueMatrix.setRotate(0,hue);//0为红色
hueMatrix.setRotate(1,hue);//1为绿色
hueMatrix.setRotate(2,hue);//2为蓝色
//饱和度
ColorMatrix saturationMatrix = new ColorMatrix();
saturationMatrix.setSaturation(saturation);
//亮度
ColorMatrix lumMatrix = new ColorMatrix();
lumMatrix.setScale(lum,lum,lum,1);
//融合
ColorMatrix imageMatrix = new ColorMatrix();
imageMatrix.postConcat(hueMatrix);
imageMatrix.postConcat(saturationMatrix);
imageMatrix.postConcat(lumMatrix);
paint.setColorFilter(new ColorMatrixColorFilter(imageMatrix));
canvas.drawBitmap(bm,0,0,paint);
return bmp;
}
}
来个例子:
新建一个primary_color.xml的布局,里面有一个ImageButton来到本地相册获取图片,然后有3个SeekBar来调节色调,饱和度以及亮度(代码如下)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageButton
android:id="@+id/id_image"
android:layout_width="300dp"
android:layout_height="300dp"
android:layout_centerHorizontal="true"
android:src="@mipmap/ic_launcher"
android:layout_marginTop="15dp"
android:layout_marginBottom="10dp"
/>
<TextView
android:id="@+id/id_hue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:text="色调"
android:layout_below="@+id/id_image"/>
<android.support.v7.widget.AppCompatSeekBar
android:id="@+id/seekbarHue"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/id_hue"/>
<TextView
android:id="@+id/id_saturation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="饱和度"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_below="@+id/seekbarHue"/>
<android.support.v7.widget.AppCompatSeekBar
android:id="@+id/seekbarSaturation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/id_saturation"/>
<TextView
android:id="@+id/id_lum"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:text="亮度"
android:layout_below="@+id/seekbarSaturation"/>
<android.support.v7.widget.AppCompatSeekBar
android:id="@+id/seekbarLum"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/id_lum"/>
</RelativeLayout>
然后我们来编写活动的代码,我们之前编写了图像处理工具类ImageHelper,然后我们用onProgressChanged监听SeekBar的变化,通过转化为数值,通过ImageHelper中的handleImageEffect方法改变图像的色调,饱和度以及亮度(代码如下)
package com.xjh.gin.image;
import android.Manifest;
import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.ImageButton;
import android.widget.SeekBar;
/**
* Created by Gin on 2017/11/25.
*/
public class PrimaryColor extends BaseActivity implements SeekBar.OnSeekBarChangeListener,View.OnClickListener {
private static final int PICK_CODE = 0X110;
private ImageButton mImage;
private SeekBar mSeekbarHue, mSeekbarSaturation, mSeekbarLum;
private static int MAX_VALUE = 255;
private static int MID_VALUE = 127;
private float mHue, mSaturation, mLum;
private String mCurreatPhotoStr;
private Bitmap bitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.primary_color);
isPermissionAllGranted(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
initView();
initEvent();
}
private void initEvent() {
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test1);
mImage.setOnClickListener(this);
mSeekbarHue.setOnSeekBarChangeListener(this);
mSeekbarSaturation.setOnSeekBarChangeListener(this);
mSeekbarLum.setOnSeekBarChangeListener(this);
mSeekbarHue.setMax(MAX_VALUE);
mSeekbarSaturation.setMax(MAX_VALUE);
mSeekbarLum.setMax(MAX_VALUE);
mSeekbarHue.setProgress(MID_VALUE);
mSeekbarSaturation.setProgress(MID_VALUE);
mSeekbarLum.setProgress(MID_VALUE);
mImage.setImageBitmap(bitmap);
}
private void initView() {
mImage = (ImageButton) findViewById(R.id.id_image);
mSeekbarHue = (SeekBar) findViewById(R.id.seekbarHue);
mSeekbarSaturation = (SeekBar) findViewById(R.id.seekbarSaturation);
mSeekbarLum = (SeekBar) findViewById(R.id.seekbarLum);
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
switch (seekBar.getId()) {
case R.id.seekbarHue:
mHue = (progress - MID_VALUE) * 1.0f / MID_VALUE * 180;
break;
case R.id.seekbarSaturation:
mSaturation = progress * 1.0f / MID_VALUE;
break;
case R.id.seekbarLum:
mLum = progress * 1.0f / MID_VALUE;
break;
}
mImage.setImageBitmap(ImageHelper.handleImageEffect(bitmap, mHue, mSaturation, mLum));
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.id_image:
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PICK_CODE);
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == PICK_CODE) {
if (data != null) {
Uri uri = data.getData();
Cursor cursor = getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
mCurreatPhotoStr = cursor.getString(idx);
cursor.close();
resizePhoto();
}
}
super.onActivityResult(requestCode, resultCode, data);
}
private void resizePhoto() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//true为不加载图片,只有宽高这类的数据
BitmapFactory.decodeFile(mCurreatPhotoStr, options);
double ratio = Math.max(options.outWidth * 1.0d / 1024f, options.outHeight * 1.0d / 1024f);//求出压缩比例
options.inSampleSize = (int) Math.ceil(ratio);//把压缩比例传入options中
options.inJustDecodeBounds = false;
bitmap = BitmapFactory.decodeFile(mCurreatPhotoStr, options);
mImage.setImageBitmap(bitmap);//压缩图片,mPhoto是压缩过后的Bitmap
}
}
项目GitHub地址:传送门