matrix 图像处理与分析 PS 色调 饱和度 亮度


android 中提供这样一个颜色矩阵来进行图像效果处理




这样的一个矩阵作为初始化的一个矩阵,因为带进去数据之后,RGB 没有变化,并没有改变原有效果





总结:

  a,b,c,d,e 控制的是新像素点的R1

  第2行,控制绿

  第3行,控制blue 

  第4行,控制的是透明度

而整个矩阵的第5列,e,j,o,t 称为颜色的偏移量,他们是一个常量

改变一个颜色,不仅仅可以使用偏移量增加,同样可以改变系数扩大比例





代码:

package com.example.imagedeal;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.Bitmap.Config;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
//在android 中通过矩阵来处理图像是非常常用的方法
//矩阵计算公式
//第一个矩阵每行* 第二个矩阵每列 = 新矩阵中的一行
public class ImageHelper {
	/**
	 * 
	 * @param bm 图像
	 * @param hun 色相
	 * @param saturation 饱和度
	 * @param lum 亮度
	 * @return
	 */
	//三个参数为所需要调整的属性值
   public static Bitmap handleImageEffect(Bitmap bm,float hun,float saturation,float lum){
	  Bitmap bmp= Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Config.ARGB_8888);
	   Canvas canvas=new Canvas(bmp);
	   Paint paint =new Paint(Paint.ANTI_ALIAS_FLAG);
	   //后面的操作都在画布上
	   
	   //创建一个图像,将所有的效果表现出来
	   ColorMatrix hunMatrix=new ColorMatrix();
	   hunMatrix.setRotate(0, hun);//red 
	   hunMatrix.setRotate(1, hun);//green
	   hunMatrix.setRotate(2, hun);//blue \
	   
	   ColorMatrix saturationMatrix=new ColorMatrix();
	   saturationMatrix.setSaturation(saturation);
	   ColorMatrix lumMatrix =new ColorMatrix();
	   //在内部也是使用颜色数组 20位一维数组  将0,6,12,18 定义的Scale 值 
	   //当RGB 三种形式以等量的形式  混合的时候就会产生白色  也就是说将rScale ,gScale ,bScale 设置同一个值,就会是白色 并且大于1,就可以增加他的亮度 。这一切都是矩阵实现的
	   lumMatrix.setScale(lum, lum, lum, 1);
	   
	   ColorMatrix iamgeMatrix=new ColorMatrix();
	   iamgeMatrix.postConcat(hunMatrix);
	   iamgeMatrix.postConcat(saturationMatrix);
	   iamgeMatrix.postConcat(lumMatrix);
	   
	   paint.setColorFilter(new ColorMatrixColorFilter(iamgeMatrix));
	   canvas.drawBitmap(bm, 0, 0, paint);
	   
	   return bmp;
   }
   
   //根据像点实现特效  底片效果
   public static Bitmap handlerImageNeative(Bitmap bm){
	   int width=bm.getWidth();
	   int height=bm.getHeight();
	   int color=0 ;//当前取出来的颜色
	   int r,g,b,a; // 保存从颜色中取出来的颜色分量
	   Bitmap bmp=Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
	   //如何遍历图片的所有像素点?
	   //bm.getWidth() 像素宽 
	   //bm.getHeight()//像素高
	   int [] oldPx=new int[width*height];// 大小可以通过 相乘得到  像素数组 存储像素点
	   int [] newPx=new int[width*height];
	   //offset 起点时 需要读取像素点偏移的量 通常为0
	   //读取数组时的一个行距  多少个算是一行 通常情况下也是使用width 与原图保持一致	 
	   //xy 第一次 读取x y 的坐标  设置为0 从起点开始
	   //width 从bitmap 中读取的像素长度
	   //height 从bitmap 中读取的像素的高度
	    
	   //
	   bm.getPixels(oldPx, 0, width, 0, 0, width, height);
	   //通过以上两行 代码就可以  将图像所有的像素点以数组的形式  保存到了oldPx 中
	   //有了这样一个像素数组 那么就好办了,for 循环
	   for(int i=0;i<width*height;i++){
		   color=oldPx[i];
		   //颜色取出来,但是我们操作的的是RGB 分量 还需要定义4个变量rgba
		   r=Color.red(color);//r 分量
		   g=Color.green(color);//g 分量
		   b=Color.green(color);
		   a=Color.alpha(color);
		   //分离了rgba 四个分量  
		   //接下来就可以通过算法对这四个分量进行操作
		   r=255-r;
		   g=255-g;
		   b=255-b;
		   //保证处理的三个值依然在255 -0 之间
		   if(r>255){
			   r=255;
		   }else if(r<0){
			   r=0;
		   }
		   
		   if(g>255){
			   g=255;
		   }else if(g<0){
			   g=0;
		   }
		   
		   if(b>255){
			   b=255;
		   }else if(b<0){
			   b=0;
		   }
		   //最后新建数组存储新的像素点
		   newPx[i]=Color.argb(a,r, g, b); //就合成了一个新的颜色  并把颜色赋给新的像素点 
		   //通过所有的循环  来做处理
		   //把数组重新设置给bitmap 的时候, 他的整个效果已经发生了新的改变
 	   }
	   bmp.setPixels(newPx, 0, width, 0, 0, width, height);
	   return bmp;
   }
   //怀旧效果
   public static Bitmap handlerImageOldPhoto(Bitmap bm){
	  return null;
   }
   //
   public static Bitmap handlerImagePixlsRelief(Bitmap bm){
	   // 因为用到前一个点,所以循环的时候,是从1开始的。
	   
	   return null;
   }
}


package com.example.imagedeal;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.GridLayout;
import android.widget.ImageView;

public class ColorMatrix extends Activity {
	private ImageView mImageView;
	private GridLayout mGroup;
	private Bitmap bitmap;
	private int mEtWidth,mEtHeight;
	private EditText [] mEts=new EditText[20];
	private float [] mColorMatrix=new float[20];//每个EditText 的具体输入值  这个20 的一维数组, 对应的就是4*5 的矩阵 这个就是核心所在
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.color_activity);
		bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.a);
		mImageView=(ImageView) findViewById(R.id.imageview);
		mGroup=(GridLayout) findViewById(R.id.group);
		mImageView.setImageBitmap(bitmap);
		//动态创建20个EditText 
		//获取gridLayout 的宽和高 
		mGroup.post(new Runnable() {
			@Override
			public void run() {
                   //控制 绘制完毕后执行 获取宽和高 4行5列
				mEtWidth=mGroup.getWidth()/5;
				mEtHeight=mGroup.getHeight()/4;
				addEts();
				initMatrix();
			}
		});
	}
	private void addEts(){
		for(int i=0;i<20;i++){
			 EditText editText =new EditText(ColorMatrix.this);
			 mEts[i]=editText;
			 mGroup.addView(editText,mEtWidth,mEtHeight);
		}
	}
	//初始化矩阵  第0,第6,12,18 都是1 其他的都是0 初始化的时候,就需要将这些editText 设置为1
	private void initMatrix(){
		for(int i=0;i<20;i++){
			if(i%6==0){
				mEts[i].setText(String.valueOf(1));
			}else{
				mEts[i].setText(String.valueOf(0));
			}
		}
	}
	public void btnChage(View view){
		getMatrix();
		setImageMatrix();
	}
	public void btnRset(View view){
		initMatrix();//重新初始化
		getMatrix();
		setImageMatrix();
	}
	private void getMatrix(){
		for(int i=0;i<20;i++){
			mColorMatrix[i]=Float.valueOf(mEts[i].getText().toString());
		}
	}
	
	//需要把颜色矩阵 作用与 图片上  产生一个图片处理效果
	private void setImageMatrix(){
	  Bitmap bmp=Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
	  android.graphics.ColorMatrix colormatrix=new android.graphics.ColorMatrix();
	  //通过set方法将一个数组变为一个颜色矩阵
	  colormatrix.set(mColorMatrix);
	  Canvas canvas=new Canvas(bmp);
	  Paint paint=new Paint(Paint.ANTI_ALIAS_FLAG);//抗锯齿
	  paint.setColorFilter(new ColorMatrixColorFilter(colormatrix));//这样便拥有了神奇的画笔
	  canvas.drawBitmap(bitmap, 0, 0, paint);
	  mImageView.setImageBitmap(bmp);//处理后的图片设置到Imageview
	}
}


package com.example.imagedeal;

import android.os.Bundle;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
// 图像分析之 RGB 模型
//色调/色相 --物体传递的颜色
//饱和度  --颜色的纯度 从0(灰) 到100% (饱和)来进行描述
//亮度/明度 --颜色 的相对明暗程度


//图像经过放大后,会呈现一个个点阵,每一个点就是一个像素点 ,通过控制RGB 的颜色 配比,就可以显示出不同颜色

//ABC   3个像素点 求b点的底片效果算法 B.r =255-B.r  B.g=255-B.g  B.b=255-B.b  每一个像素点经过这样的换算,就是一个底片效果
//老照片效果 
public class MainActivity extends Activity implements OnSeekBarChangeListener {
	private ImageView iv;
	private SeekBar seek_hue;
	private SeekBar seek_saturation;
	private SeekBar seek_lum;
	private static int MAX_VALUE = 255;// 颜色取值0-255
	private static int MID_VALUE = 127;
	private float mHue,mSatauration,mLum;
   private Bitmap bitmap;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.a);
		setContentView(R.layout.activity_main);
		iv = (ImageView) findViewById(R.id.imageview);
		seek_hue = (SeekBar) findViewById(R.id.seekbar_hue);
		seek_saturation = (SeekBar) findViewById(R.id.seekbar_saturation);
		seek_lum = (SeekBar) findViewById(R.id.seekbar_lum);

		seek_hue.setOnSeekBarChangeListener(this);
		seek_saturation.setOnSeekBarChangeListener(this);
		seek_lum.setOnSeekBarChangeListener(this);

		seek_hue.setMax(MAX_VALUE);
		seek_saturation.setMax(MAX_VALUE);
		seek_lum.setMax(MAX_VALUE);

		seek_hue.setProgress(MID_VALUE);
		seek_saturation.setProgress(MID_VALUE);
		seek_lum.setProgress(MID_VALUE);
		iv.setImageBitmap(bitmap);
	}

	@Override
	public void onProgressChanged(SeekBar seekBar, int progress,
			boolean fromUser) {
		switch (seekBar.getId()) {
		case R.id.seekbar_hue://色调
			//这样一个取值范围 并不是固定的,是一个经验值,最能作用与ColorMatrix 
			mHue=(progress-MID_VALUE)*1.0F/MID_VALUE*180;
			break;
		case R.id.seekbar_saturation:
			mSatauration=progress*1.0F/MID_VALUE;// 取值返回是0-2
			break;
		case R.id.seekbar_lum:
			mLum=progress*1.0F/MID_VALUE;//
			break;
		default:
			break;
		}
		
		iv.setImageBitmap(ImageHelper.handleImageEffect(bitmap, mHue, mSatauration, mLum));
	}

	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {

	}

	@Override
	public void onStopTrackingTouch(SeekBar seekBar) {

	}

}

package com.example.imagedeal;

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

public class PixelsEfect extends Activity{
	private ImageView iv1,iv2,iv3,iv4;
     @Override
    protected void onCreate(Bundle savedInstanceState) {
    	super.onCreate(savedInstanceState);
    	setContentView(R.layout.pixels_activity);
    	Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.a);
    	iv1=(ImageView) findViewById(R.id.image1);
    	iv2=(ImageView) findViewById(R.id.image2);
    	iv3=(ImageView) findViewById(R.id.image3);
    	iv4=(ImageView) findViewById(R.id.image4);
    	iv1.setImageBitmap(bitmap);
    	iv2.setImageBitmap(ImageHelper.handlerImageNeative(bitmap));
    }
}

activity_main

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

   <ImageView
       android:id="@+id/imageview"
       android:layout_width="200dp"
       android:layout_height="200dp"
       android:layout_centerHorizontal="true"
       android:layout_marginTop="24dp" />

   <SeekBar 
       android:id="@+id/seekbar_hue"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_below="@id/imageview"
       />
     <SeekBar 
       android:id="@+id/seekbar_saturation"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_below="@id/seekbar_hue"
       />
       <SeekBar 
       android:id="@+id/seekbar_lum"
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_below="@id/seekbar_saturation"
       />
</RelativeLayout>


color_activity

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <ImageView
        android:id="@+id/imageview"
        android:layout_height="0dp"
        android:layout_width="match_parent"
        android:layout_weight="2" />

    <GridLayout
        android:id="@+id/group"
        android:layout_width="match_parent"
        android:layout_weight="3"
        android:columnCount="5"
         android:layout_height="0dp"
        android:rowCount="4" >
    </GridLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="btnChage"
            android:text="change" />

        <Button
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:onClick="btnRset"
            android:text="reset" />
    </LinearLayout>

</LinearLayout>


pixels activity 

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/image1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <ImageView
            android:id="@+id/image2"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal" >

        <ImageView
            android:id="@+id/image3"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />

        <ImageView
            android:id="@+id/image4"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1" />
    </LinearLayout>

</LinearLayout>


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值