Android中的图像处理

来自于慕课网

图像色彩变换

图像处理之---通过改变图像的色调/色相,饱和度和亮度来改变图像的显示效果。

色光三元素中的三个概念:

 色调/色相:指的是物体传递的颜色

 饱和度:指的是颜色的纯度,从0(灰)到100%(饱和)来进行描述

 亮度:指的是相对的明暗程度

RGBA模型---R代表red,G代表green,B代表blue,A代表alpha控制图片的透明度

通过改变色光三元素的值来进行图片处理:

public static Bitmap handleImageEffect(Bitmap bm,float hue,float saturation,float lum){
    //根据传进来的bitmap新建一个bitmap,因为不能直接对bitmap进行修改
    Bitmap bitmap = Bitmap.createBitmap(bm.getWidth(),bm.getHeight(),Bitmap.Config.ARGB_8888);//32位ARGB位图
    Canvas canvas= new Canvas(bitmap);
    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    //设置色相
    ColorMatrix hueMatrix = new ColorMatrix();
    hueMatrix.setRotate(0,hue);
    hueMatrix.setRotate(1,hue);
    hueMatrix.setRotate(2,hue);

    //设置饱和度
    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 bitmap;
}
图像处理之---通过矩阵变换

 通过改变颜色矩阵中的值来进行图像处理

将颜色矩阵初始化为下图中的数值后,与颜色矩阵分量相乘的结果如图中右下角,表示对图像并没有进行改变,因为RGBA的值没有发生改变。

颜色矩阵中的第一行对红色进行处理,第二行对绿色进行处理,第三行对蓝色进行处理,第四行对透明度进行处理;颜色矩阵的第五列是颜色偏移量

图像处理之---像素点

通过改变图片像素点的a,r,g,b分量的值来对图片进行改变

//底片效果
public static Bitmap handleImageNegative(Bitmap bm) {
    //获取传入图像的宽和高
    int width = bm.getWidth();
    int height = bm.getHeight();
    //像素点的中间分量
    int color;
    //像素点的RGBA分量
    int r, g, b, a;
    //根据传进来的bitmap新建一个bitmap,因为不能直接对bitmap进行修改
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//32位ARGB位图
    //将图像的原始像素点保存到老数组中
    int[] oldPx = new int[width * height];
    //将改变后图像的像素点保存到新数组中
    int[] newPx = new int[width * height];
    //获取图像的像素点
    bm.getPixels(oldPx, 0, width, 0, 0, width, height);

    for (int i = 0; i < width * height; i++) {
        color = oldPx[i];
        //颜色值的RGBA分量
        r = Color.red(color);
        g = Color.green(color);
        b = Color.blue(color);
        a = Color.alpha(color);

        r = 255 - r;
        g = 255 - g;
        b = 255 - b;
        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.setPixels(newPx, 0, width, 0, 0, width, height);
    return bitmap;
}

//怀旧效果
public static Bitmap handleImageOldPhoto(Bitmap bm) {
    //获取传入图像的宽和高
    int width = bm.getWidth();
    int height = bm.getHeight();
    //像素点的中间分量
    int color = 0;
    //像素点的RGBA分量
    int r, g, b, a, r1, g1, b1;
    //根据传进来的bitmap新建一个bitmap,因为不能直接对bitmap进行修改
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//32位ARGB位图
    //将图像的原始像素点保存到老数组中
    int[] oldPx = new int[width * height];
    //将改变后图像的像素点保存到新数组中
    int[] newPx = new int[width * height];
    //获取图像的像素点
    bm.getPixels(oldPx, 0, width, 0, 0, width, height);

    for (int i = 0; i < width * height; i++) {
        color = oldPx[i];
        //颜色值的RGBA分量
        r = Color.red(color);
        g = Color.green(color);
        b = Color.blue(color);
        a = Color.alpha(color);

        r1 = (int) (0.393 * r + 0.769 * g + 0.189 * b);
        g1 = (int) (0.349 * r + 0.686 * g + 0.168 * b);
        b1 = (int) (0.272 * r + 0.534 * g + 0.131 * b);
        if (r1 > 255) {
            r1 = 255;
        }

        if (g1 > 255) {
            g1 = 255;
        }

        if (b1 > 255) {
            b1 = 255;
        }
        //将改变后的像素点赋值给新的数组
        newPx[i] = Color.argb(a, r1, g1, b1);
    }
    bitmap.setPixels(newPx, 0, width, 0, 0, width, height);
    return bitmap;
}

//浮雕效果
public static Bitmap handleImagePixelsRelief(Bitmap bm) {
    //获取传入图像的宽和高
    int width = bm.getWidth();
    int height = bm.getHeight();
    //像素点的中间分量
    int color = 0,colorBefore = 0;
    //像素点的RGBA分量
    int r, g, b, a, r1, g1, b1;
    //根据传进来的bitmap新建一个bitmap,因为不能直接对bitmap进行修改
    Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);//32位ARGB位图
    //将图像的原始像素点保存到老数组中
    int[] oldPx = new int[width * height];
    //将改变后图像的像素点保存到新数组中
    int[] newPx = new int[width * height];
    //获取图像的像素点
    bm.getPixels(oldPx, 0, width, 0, 0, width, height);

    for (int i = 1; i < width * height; i++) {
        colorBefore = oldPx[i-1];
        //颜色值的RGBA分量
        r = Color.red(colorBefore);
        g = Color.green(colorBefore);
        b = Color.blue(colorBefore);
        a = Color.alpha(colorBefore);

        color = oldPx[i];

        r1 = Color.red(color);
        g1 = Color.green(color);
        b1 = Color.blue(color);

        r = (r-r1+127);
        g = (g-g1+127);
        b = (b-b1+127);
        if (r > 255) {
            r = 255;
        }

        if (g > 255) {
            g = 255;
        }

        if (b > 255) {
            b = 255;
        }
        //将改变后的像素点赋值给新的数组
        newPx[i] = Color.argb(a, r, g, b);
    }
    bitmap.setPixels(newPx, 0, width, 0, 0, width, height);
    return bitmap;
}

图像变换

图像变换之---矩阵法

图像坐标的矩阵变换,单位向量C是原始坐标点,矩阵A是变换矩阵,新的坐标点R就等于A*C。

通过矩阵变换可以实现的效果有:平移、旋转、缩放和错切

改变矩阵中相应的值来达到不同的效果

图像变换之---画笔风格法

Xfermode

shader

像素块---drawBitmapMesh