android图像处理系列之三--图片色调饱和度 色相 亮度处理
程序员文章站
2022-07-14 16:52:12
...
原图:
处理后:
下面贴代码:
一、图片处理层:
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 aaa@qq.com * */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 aaa@qq.com * */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>
上一篇: UnityShader-屏幕后处理(调节亮度,饱和度,对比度)
下一篇: 图像拼接 - 多波段融合