几种图片处理效果的整理应用

package com.example.test.qtest;

import android.graphics.Bitmap;
import android.graphics.Color;

/**
 * Created by scq on 17-2-13.
 */
public class ImageProcessEffect {

    /**
     * 底片效果
     *
     * ABC3个像素点
     * 求B点的底片效果算法:
     * B.r = 255 - B.r;
     * B.g = 255 - B.g;
     * B.b = 255 - B.b;
     */
    public Bitmap filmEffect(Bitmap bm) {

        //返回的就是像素点个数
        int width = bm.getWidth();
        int height = bm.getHeight();

        int color; //用于存储当前取出来的颜色

        int r, g, b ,a;//用于保存颜色中取出来的四个分量

        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        //保存像素点数组到图像
        int[] oldPx = new int[width * height];

        int[] newPx = new int[width * height];

        //第三个参数 stride 多少个算一行 一般为width
        bm.getPixels(oldPx, 0, width, 0, 0, width, height);

        for (int i = 0; i < width * height; i++) {
            color = oldPx[i];
            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);

        }
        bmp.setPixels(newPx, 0, width, 0, 0, width, height);
        return bmp;
    }

    /**
     * 怀旧效果
     *
     * 求像素点的老照片效果算法
     * newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
     * newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
     * newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);
     */
    public Bitmap nostalgicEffect(Bitmap bm) {

        int width = bm.getWidth();
        int height = bm.getHeight();

        int color = 0;

        int r, g, b, a, r1, b1, g1;

        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        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];
            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);

        }
        bmp.setPixels(newPx, 0, width, 0, 0, width, height);
        return bmp;

    }

    /**
     * 浮雕效果
     *
     * ABC
     * 求B点的浮雕效果算法:
     * B.r = C.r - B.r + 127
     * B.g = C.g - B.g + 127
     * B.r = C.b - B.b + 127
     */
    public Bitmap reliefEffect(Bitmap bm) {

        int width = bm.getWidth();
        int height = bm.getHeight();

        int color = 0;
        int colorBefore = 0;

        int r, g, b, a;

        int r1, b1, g1;

        int oldPx[] = new int[width * height];
        int newPx[] = new int[width * height];

        Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

        bm.getPixels(oldPx, 0, width, 0, 0, width, height);

        //注意要从1开始!!!
        for (int i = 1; i < width * height; i++) {

            colorBefore = oldPx[i - 1];
            a = Color.alpha(colorBefore);
            r = Color.red(colorBefore);
            g = Color.green(colorBefore);
            b = Color.blue(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);
        }
        bmp.setPixels(newPx, 0, width, 0, 0, width, height);
        return bmp;
    }
    /**
     * 模糊效果
     *
     * 算法原理:
     * 简单算法将像素周围八个点包括自身共九个点RGB值分别相加后平均,当前像素点的RGB值
     * 复杂算法采用高斯模糊
     * 高斯矩阵 int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };
     * 将九个点的RGB值分别与高斯矩阵中的对应项相乘的和,再除以一个相应的值作为当前像素点的RGB
     */
    public Bitmap blurEffect(Bitmap bmp){
        int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };  // 高斯矩阵
        int delta = 15; // 除以值 值越小图片会越亮,越大则越暗
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        int pixColor = 0;
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int newR, newG, newB;
        int pos = 0;    //位置
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        //循环赋值
        for (int i = 1; i < height-1; i++) {
            for (int k = 1; k < width-1; k++) {
                pos = 0;
                newR = 0;
                newG = 0;
                newB = 0;
                for (int m = -1; m <= 1; m++)  //宽不变
                {
                    for (int n = -1; n <= 1; n++) //高先变
                    {
                        pixColor = pixels[(i + m) * width + k + n];
                        pixR = Color.red(pixColor);
                        pixG = Color.green(pixColor);
                        pixB = Color.blue(pixColor);
                        //3*3像素相加
                        newR = newR + (int) (pixR * gauss[pos]);
                        newG = newG + (int) (pixG * gauss[pos]);
                        newB = newB + (int) (pixB * gauss[pos]);
                        pos++;
                    }
                }
                newR /= delta;
                newG /= delta;
                newB /= delta;
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                pixels[i * width + k] = Color.argb(255, newR, newG, newB);
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 光照效果
     *
     * 算法原理:(前一个像素点RGB-当前像素点RGB+127)作为当前像素点RGB值
     * 在ABC中计算B点浮雕效果(RGB值在0~255)
     * B.r = C.r - B.r + 127
     * B.g = C.g - B.g + 127
     * B.b = C.b - B.b + 127
     * 光照中心取长宽较小值为半径,也可以自定义从左上角射过来
     */
    public Bitmap lightingEffect(Bitmap bmp){
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        int pixColor = 0;
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        //围绕圆形光照
        int centerX = width / 2;
        int centerY = height / 2;
        int radius = Math.min(centerX, centerY);
        float strength = 150F;  //光照强度100-150
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 1; i < height-1; i++) {
            for (int k = 1; k < width-1; k++) {
                //获取前一个像素颜色
                pixColor = pixels[width * i + k];
                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);
                newR = pixR;
                newG = pixG;
                newB = pixB;
                //计算当前点到光照中心的距离,平面坐标系中两点之间的距离
                int distance = (int) (Math.pow((centerY-i), 2) + Math.pow((centerX-k), 2));
                if(distance < radius*radius)
                {
                    //按照距离大小计算增强的光照值
                    int result = (int)(strength*( 1.0-Math.sqrt(distance) / radius ));
                    newR = pixR + result;
                    newG = newG + result;
                    newB = pixB + result;
                }
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                pixels[width * i + k] = Color.argb(255, newR, newG, newB);
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 锐化效果 拉普拉斯算子处理
     *
     * 算法原理:
     * 锐化基本思想是加强图像中景物的边缘和轮廓,使图像变得清晰
     * 而图像平滑是使图像中边界和轮廓变得模糊
     *
     * 拉普拉斯算子图像锐化
     * 获取周围9个点的矩阵乘以模板9个的矩阵 卷积
     */
    public Bitmap sharpeningEffect(Bitmap bmp) {
        //拉普拉斯算子模板 { 0, -1, 0, -1, -5, -1, 0, -1, 0 } { -1, -1, -1, -1, 9, -1, -1, -1, -1 }
        int[] laplacian = new int[] {  -1, -1, -1, -1, 9, -1, -1, -1, -1 };
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int pixColor = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        int idx = 0;
        float alpha = 0.3F;  //图片透明度
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        //图像处理
        for (int i = 1; i < height - 1; i++) {
            for (int k = 1; k < width - 1; k++) {
                idx = 0;
                newR = 0;
                newG = 0;
                newB = 0;
                for (int n = -1; n <= 1; n++)   //取出图像3*3领域像素
                {
                    for (int m = -1; m <= 1; m++)  //n行数不变 m列变换
                    {
                        pixColor = pixels[(i + n) * width + k + m];  //当前点(i,k)
                        pixR = Color.red(pixColor);
                        pixG = Color.green(pixColor);
                        pixB = Color.blue(pixColor);
                        //图像像素与对应摸板相乘
                        newR = newR + (int) (pixR * laplacian[idx] * alpha);
                        newG = newG + (int) (pixG * laplacian[idx] * alpha);
                        newB = newB + (int) (pixB * laplacian[idx] * alpha);
                        idx++;
                    }
                }
                newR = Math.min(255, Math.max(0, newR));
                newG = Math.min(255, Math.max(0, newG));
                newB = Math.min(255, Math.max(0, newB));
                //赋值
                pixels[i * width + k] = Color.argb(255, newR, newG, newB);
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 冰冻效果
     * **/
    public Bitmap frozenEffect(Bitmap bmp){
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        int pixColor = 0;
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int newColor = 0;
        int newR = 0;
        int newG = 0;
        int newB =0;
        int[] pixels = new int[width * height];
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        for (int i = 0; i < height; i++){
            for (int k = 0; k < width; k++){
                //获取前一个像素颜色
                pixColor = pixels[width * i + k];
                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);
                //红色
                newColor = pixR - pixG - pixB;
                newColor = newColor * 3 / 2;
                if(newColor < 0) {
                    newColor = -newColor;
                }
                if(newColor >255) {
                    newColor = 255;
                }
                newR = newColor;
                //绿色
                newColor = pixG - pixB - pixR;
                newColor = newColor * 3 / 2;
                if(newColor < 0) {
                    newColor = -newColor;
                }
                if(newColor >255) {
                    newColor = 255;
                }
                newG = newColor;
                //蓝色
                newColor = pixB - pixG - pixR;
                newColor = newColor * 3 / 2;
                if(newColor < 0) {
                    newColor = -newColor;
                }
                if(newColor >255) {
                    newColor = 255;
                }
                newB = newColor;
                pixels[width * i + k] = Color.argb(255, newR, newG, newB);
            }
        }
        bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
        return bitmap;
    }

    /**
     * 素描效果
     * **/
    public Bitmap sketchEffect(Bitmap bmp){
        //创建新Bitmap
        int width = bmp.getWidth();
        int height = bmp.getHeight();
        int[] pixels = new int[width * height];    //存储变换图像
        int[] linpix = new int[width * height];     //存储灰度图像
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
        bmp.getPixels(pixels, 0, width, 0, 0, width, height);
        int pixColor = 0;
        int pixR = 0;
        int pixG = 0;
        int pixB = 0;
        int newR = 0;
        int newG = 0;
        int newB = 0;
        //灰度图像
        for (int i = 1; i < width - 1; i++) {
            for (int j = 1; j < height - 1; j++)   //拉普拉斯算子模板 { 0, -1, 0, -1, -5, -1, 0, -1, 0
            {
                //获取前一个像素颜色
                pixColor = pixels[width * i + j];
                pixR = Color.red(pixColor);
                pixG = Color.green(pixColor);
                pixB = Color.blue(pixColor);
                //灰度图像
                int gray=(int)(0.3*pixR+0.59*pixG+0.11*pixB);
                linpix[width * i + j] = Color.argb(255, gray, gray, gray);
                //图像反向
                gray=255-gray;
                pixels[width * i + j] = Color.argb(255, gray, gray, gray);
            }
        }
        int radius = Math.min(width/2, height/2);
        int[] copixels = gaussBlur(pixels, width, height, 10, 10/3);   //高斯模糊 采用半径10
        int[] result = colorDodge(linpix, copixels);   //素描图像 颜色减淡
        bitmap.setPixels(result, 0, width, 0, 0, width, height);
        return bitmap;
    }

    //高斯模糊
    public static int[] gaussBlur(int[] data, int width, int height, int radius,
                                  float sigma) {

        float pa = (float) (1 / (Math.sqrt(2 * Math.PI) * sigma));
        float pb = -1.0f / (2 * sigma * sigma);

        // generate the Gauss Matrix
        float[] gaussMatrix = new float[radius * 2 + 1];
        float gaussSum = 0f;
        for (int i = 0, x = -radius; x <= radius; ++x, ++i) {
            float g = (float) (pa * Math.exp(pb * x * x));
            gaussMatrix[i] = g;
            gaussSum += g;
        }

        for (int i = 0, length = gaussMatrix.length; i < length; ++i) {
            gaussMatrix[i] /= gaussSum;
        }

        // x direction
        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                float r = 0, g = 0, b = 0;
                gaussSum = 0;
                for (int j = -radius; j <= radius; ++j) {
                    int k = x + j;
                    if (k >= 0 && k < width) {
                        int index = y * width + k;
                        int color = data[index];
                        int cr = (color & 0x00ff0000) >> 16;
                        int cg = (color & 0x0000ff00) >> 8;
                        int cb = (color & 0x000000ff);

                        r += cr * gaussMatrix[j + radius];
                        g += cg * gaussMatrix[j + radius];
                        b += cb * gaussMatrix[j + radius];

                        gaussSum += gaussMatrix[j + radius];
                    }
                }

                int index = y * width + x;
                int cr = (int) (r / gaussSum);
                int cg = (int) (g / gaussSum);
                int cb = (int) (b / gaussSum);

                data[index] = cr << 16 | cg << 8 | cb | 0xff000000;
            }
        }

        // y direction
        for (int x = 0; x < width; ++x) {
            for (int y = 0; y < height; ++y) {
                float r = 0, g = 0, b = 0;
                gaussSum = 0;
                for (int j = -radius; j <= radius; ++j) {
                    int k = y + j;
                    if (k >= 0 && k < height) {
                        int index = k * width + x;
                        int color = data[index];
                        int cr = (color & 0x00ff0000) >> 16;
                        int cg = (color & 0x0000ff00) >> 8;
                        int cb = (color & 0x000000ff);

                        r += cr * gaussMatrix[j + radius];
                        g += cg * gaussMatrix[j + radius];
                        b += cb * gaussMatrix[j + radius];

                        gaussSum += gaussMatrix[j + radius];
                    }
                }

                int index = y * width + x;
                int cr = (int) (r / gaussSum);
                int cg = (int) (g / gaussSum);
                int cb = (int) (b / gaussSum);
                data[index] = cr << 16 | cg << 8 | cb | 0xff000000;
            }
        }

        return data;
    }

     // 颜色减淡
    private static int[] colorDodge(int[] baseColor, int[] mixColor) {

        for (int i = 0, length = baseColor.length; i < length; ++i) {
            int bColor = baseColor[i];
            int br = (bColor & 0x00ff0000) >> 16;
            int bg = (bColor & 0x0000ff00) >> 8;
            int bb = (bColor & 0x000000ff);

            int mColor = mixColor[i];
            int mr = (mColor & 0x00ff0000) >> 16;
            int mg = (mColor & 0x0000ff00) >> 8;
            int mb = (mColor & 0x000000ff);

            int nr = colorDodgeFormular(br, mr);
            int ng = colorDodgeFormular(bg, mg);
            int nb = colorDodgeFormular(bb, mb);

            baseColor[i] = nr << 16 | ng << 8 | nb | 0xff000000;
        }
        return baseColor;
    }

    private static int colorDodgeFormular(int base, int mix) {

        int result = base + (base * mix) / (255 - mix);
        result = result > 255 ? 255 : result;
        return result;

    }

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值