Matrix与坐标变换

ColorMatrix色彩变换

  • 对于色彩的存储,Bitmap类使用一个32位的数值来保存,红,绿,蓝以及透明度各占8位,每个色彩分量的取值范围是0~255,透明度为0表示完全透明,为255时色彩完全可见
色彩矩阵的表示:
  • 由于一个色彩信息包含R、G、B、Alpha信息,所以,必须使用一个四阶色彩变幻矩阵来修改色彩的每一个分量,对于色彩矩阵来说色彩顺序是R、G、B、A
  • 如果想要原有的R色上增加一些分量,那么就要在四阶矩阵上在加一阶来表示平移变换,使用四阶色彩 变换矩阵来修改颜色,只能对色彩 的每个分量值进行乘(除)运算,如果要对这些分量值进行加减法运算(平移变换),则只能通过五阶矩阵来完成。
Android中的色彩变换矩阵
  • 在Android中,色彩变换矩阵的表示形式也是五阶,Android中的色彩变换矩阵是使用ColorMatri类来表示的,使用ColorMatrix类的方法如下:
ColorMatrix colormatrix  = new ColorMatrix(new float[]{
    1, 0, 0, 0, 0,
    0, 1, 0, 0, 0,
    0, 0, 1, 0, 0,
    0, 0, 0, 0.5, 0,
 });
 paint.setCoorFilter(new ColormatrixColorFilter(colorMatrix));

eg:


public class MyMatrixColorView extends View {
    private Paint paint;
    private Bitmap bitmap;
    public MyMatrixColorView(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setAntiAlias(true);
        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog);
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(bitmap, null, new Rect(0, 0, 500, 500* bitmap.getHeight() / bitmap.getWidth()), paint);
        canvas.translate(510, 0);
        ColorMatrix colorMatrix = new ColorMatrix(new float[]{
                0, 0, 0, 0, 0,
                0, 0, 0, 0, 0,
                0, 0, 1, 0, 0,
                0, 0, 0, 1, 0,
        });
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
        canvas.drawBitmap(bitmap, null, new Rect(0, 0, 500, 500 * bitmap.getHeight()/bitmap.getWidth()), paint);
    }
}

在这里插入图片描述

色彩运算的几种方式:
  • 色彩的平移运算
    (1) 增加色彩的饱和度
    • 实际上是色彩的加法运算,其实就是在色彩变换矩阵的最后一列加上某个值,这样就可以增加特定的色彩饱和度
      eg:
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        1, 0, 0, 0, 0,
        0, 1, 0, 0, 50,
        0, 0, 1, 0, 0,
        0, 0, 0, 1, 0,
});
  • 用每个像素所对应的色彩数组来乘以色彩变换矩阵,结果就是变换后的当前点的颜色值
    (2)色彩反转/反相功能

  • 色彩平移除增加指定色彩的饱和度以外,另一个应用就是色彩反转,也就是Photoshop中的反相功能,色彩反转就是求出每个颜色的补值来作为目标图像的对应颜色值

ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        -1, 0, 0, 0,255,
        0, -1, 0, 0, 255,
        0, 0, -1, 0, 255,
        0, 0, 0, 1, 0,
});

在这里插入图片描述

  • 色彩的缩放运算
    (1)调节亮度

  • 色彩的缩放运算其实就是色彩的乘法运算,将色彩变换矩阵对角线上分别代表R,G, B, A的几个之分别乘以指定的值,就是所谓的缩放运算,我们可以对某个颜色值进行放大/缩小运算,但是党对R,G,B,A同时进行放大/缩小运算时,就是对亮度的调节

  • eg:亮度调大1.2倍:


ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        1.2f, 0, 0, 0, 0,
        0, 1.2f, 0, 0, 50,
        0, 0, 1.2f, 0, 0,
        0, 0, 0, 1.2f, 0,
});

在这里插入图片描述
(2)通道输出

  • 由于再色彩变换矩阵中对角线上的数的取值范围为0~1,所以,当取0时,这个色彩就完全不显示;当R,G都取0,而独有B取1时 ,就只显示蓝色,所形成的图像也就是我通常所说的蓝色通道

(3)色彩的旋转运算

  • 使用RGB三色建立立体坐标系,把RGB色彩值看作是三维空间的三个方向的坐标,可以将一个色彩值看作是三维空间中的一个点,当围绕 红色轴旋转时,是对图片进行红色色相的调节,当围绕蓝色轴旋转时,是对图片进行蓝色色相的调节,当围绕绿色轴旋转时,是对图片进行绿色色相的调节

  • 色彩的投射运算

  • 利用其他色彩分量的倍数来改变自己的色彩分量的值,就叫做投射运算

  • eg: 黑白照片:

ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        0.213f, 0.715f, 0.072f, 0, 0,
        0.213f, 0.715f, 0.072f, 0, 0,
        0.213f, 0.715f, 0.072f, 0, 0,
        0, 0, 0, 1, 0,
});

在这里插入图片描述

  • 去色原理:只要把R,G,B三通道的色彩信息设置成一样,即R=G=B,图像就编程了灰色,并且为了保证图像亮度不变,同一个通道中的R+G+B = 1

  • 0.213, 0.715, 0.072三个数字的来历:在作用域人眼的光纤中,彩色光要明显强于无色光,如果对一张图像按照RGB平分给图像去色,人眼会明显感觉图像变暗了,另外在彩色图像中能够识别的一些细节也可能丢失

  • eg: 色彩反差:(红绿反差)

ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        0, 1, 0, 0, 0,
        1, 0, 0, 0, 0,
        0, 0, 1, 0, 0,
        0, 0, 0, 1, 0,
});

在这里插入图片描述

  • 红绿反差的关键就是第一行利用绿色来代替 红色,第二行利用红色来代替绿色
  • eg: 照片做旧:
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        1/2f, 1/2f, 1/2f, 0,  0,
        1/3f, 1/3f, 1/3f, 0, 0,
        1/4f, 1/4f, 1/4f, 0, 0,
        0,0,0,1,0,
});

[外链图片转存失败(img-6KfSQcJl-1562243584764)(en-resource://database/5280:0)]

ColorMatrix函数

  • 在Android中,ColorMatrix自带一些函数,用来帮助我们完成调整饱和度、色彩旋转等操作
ColorMatrix有三个构造函数:
ColorMatrix()
ColorMatrix(float[]  src)
ColorMatrix(ColorMatrix src)//利用一个ColorMatrix实例来复制一个一样的ColorMatrix对象
设置和重置函数
public void set(ColorMatrix src);
public void set(float[] src)
public void reset()

//重置后,对应的数组如下:
[ 1 0 0  0 0 -red vector
  0 1 0 0 0 -green vector
  0 0 1 0 0  -blue vector
  0 0 0 1 0] -alpha vector
setSaturation()函数–设置饱和度
  • 上面讲述了如何提高一个颜色分量的饱和度,这个函数是用来提高整体的色彩饱和度的
//同时增强R,G,B的色彩饱和度
//sat 表示把当前色彩饱和度放大的倍数,取值为0时完全无色彩(灰度图像);当取值为1时,色彩不进行变动,当取值大于1时,显示色彩过渡饱和
public void setSaturation(float sat)

eg:

private ImageView imageView;
private SeekBar seekBar;
private Bitmap bitmap;
private Bitmap tempBitmap;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_matrix);
    imageView = (ImageView) findViewById(R.id.image_bitmap);
    seekBar = (SeekBar)findViewById(R.id.seekbar);
    bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.dog);
    tempBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            Bitmap bitmap1 = handleColorMatrixBmp(progress);
            imageView.setImageBitmap(bitmap1);
        }


        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {


        }


        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {


        }
    });
}


private Bitmap handleColorMatrixBmp(int progress) {
    //创建一个相同尺寸的可变长的位图去,用于绘制调色后的图片
    Canvas canvas = new Canvas(tempBitmap);
    Paint paint = new Paint();
    ColorMatrix colorMatrix = new ColorMatrix();
    colorMatrix.setSaturation(progress);
    paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
    canvas.drawBitmap(bitmap, 0, 0, paint);
    return tempBitmap;
}
setScale()函数----色彩缩放
//四个参数分别对应R,G,B, A颜色值的缩放倍数
public void setScale(float rScale, float gScale, float bScale, float aScale)

eg:仅将 绿色放大1.3倍


canvas.drawBitmap(bitmap, null, new Rect(0, 0,500,500 * bitmap.getHeight() / bitmap.getWidth()), paint);
        canvas.save();
        canvas.translate(510, 0);
//生成色彩变换矩阵
        ColorMatrix colorMatrix =  new ColorMatrix();
        colorMatrix.setScale(1, 1.3f, 1,1);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
                canvas.drawBitmap(bitmap, null, new Rect(0, 0, 500, 500 * bitmap.getHeight()/ bitmap.getWidth()), paint);

[外链图片转存失败(img-LOl3Zu3U-1562243584765)(en-resource://database/5282:1)]

setRotate()函数----色彩旋转
//将旋转围绕某一个颜色轴进行
axis=0 围绕红色轴旋转
axis=1围绕绿色轴进行旋转
axis=2围绕蓝色轴进行旋转
public void setRotate(int axis, float degrees);
ColorMatrix相乘
//乘法规则为matA x matB,然后将结果作为当前ColorMatrix的值
public void setConcat(ColorMatrix matA, ColorMatrix matB)

//假设当前矩阵为A,那么preConcat()的含义就是将当前矩阵A乘以prematrix
public void peConcat(ColorMatrix prematrix)

//postmatrix矩阵乘以当前矩阵A
public void postConcat(ColorMatrix postmatrix)

猜你喜欢

转载自blog.csdn.net/qq_39424143/article/details/94651985