Java美颜相机入门(图像处理实现各种滤镜算法)

 一、思路分析

  一款简易美颜相机的功能我们可以简单分为两大块:1.图像处理    2.功能区

最终的效果图如下: 

 二、代码分析

    图像处理工具的本质是处理像素点,而像素点的本质就是一种颜色,每一个像素点都有RGB三原色(0-255),0-255为一个字节。

 图像处理知识:

  1. 图像处理的本质是在修改图片的像素值,而每一个像素点的本质是RGB三原色组成,其值范围0-255
  2. 图片的本质是一个int型的二维数组,所以图像 = int[ ] [ ];
  3. Color类可以实现数字颜色的转化。色即是数,数即是色。
  4. (1)RGB数字构成颜色:Color color = new Color(200,100,150); 其值在0-255之间

       (2)int数字构成颜色:Color color = new Color(842179),其值在int范围内即可。Int最大到21亿

因为高位补1会超过255.

获取RGB三原色的分量值:

  1.取出所有的像素值,把像素值转为Color对象,通过调用Color对象的getRed,getGreen,getBlue方法获取

 2.通过将像素值右移相应的位数,再进行与操作

 

 

  1. 左移运算: int pixel = buffimage.getRGB(j, i);

        1Byte(字节) = 8bit(位)

位运算:

         在Java中int是有4个字节,RGB是三个字节的长度(0-255是一个字节),通过左移运算      把三个Byte合成了一个int,1Byte(字节) = 8bit(位)。R红色<<移动了16位,G绿色<<移动了8位,B蓝色不移动,通过位移操作总共移动了24位。

源代码:

    这些滤镜就是一些算法,对图片的像素点RGB三原色进行修改,下面我讲一下这些滤镜效果的实现思路:

  • 这些滤镜就是一些算法,对图片的像素点RGB三原色进行修改。
  • 下面我讲一下这些滤镜效果的实现思路
  • 马赛克效果:在固定范围内放大像素点。
  • 灰度效果:1.取RGB三种颜色的平均值,则画出灰度图
  •                   2.取三种颜色的最大值/最小值
  • 黑白滤镜:计算RGB三原色平均值,如果平均值>=100,则平均值为255,不是,平均值为0
  • 去色滤镜:RGB取三种颜色的最大值和最小值的平均值
  • 单色滤镜:就是只保留一种颜色,其他颜色设为0
  • 底片/反向滤镜:就是RGB三种颜色分别取255的差值
  • 怀旧滤镜:R = 0.393r + 0.769g + 0.189b
  •                   G = 0.349r + 0.686g + 0.168b
  •                   B = 0.272r + 0.534g + 0.131b
  • 褐色滤镜:r = r * 0.393 + g * 0.769 + b * 0.189; 
                      g = r * 0.349 + g * 0.686 + b * 0.168; 
                      b = r * 0.272 + g * 0.534 + b * 0.131;
  • 连环画滤镜:公式: R = |g – b + g + r| * r / 256

                                     G = |b – g + b + r| * r / 256;

                                     B = |b – g + b + r| * g / 256;

  • 冰冻滤镜:公式: r = (r-g-b)*3/2; 
                                  g = (g-r-b)*3/2; 
                                  b = (b-g-r)*3/2;

  • 熔铸滤镜:公式: r = r*128/(g+b +1); 
                                 g = g*128/(r+b +1); 
                                 b = b*128/(g+r +1);

  • 浮雕效果:用当前点的RGB值减去相邻点的RGB值并加上128作为新的RGB值

  • 放大镜:不要跳过像素点来放大

  • Java程序真正是运行在我们的虚拟机上面的,程序>jvm(虚拟机)>os>总线>屏幕。
  • 利用缓冲区可以加快像素点的绘制速度,思路:把所有处理好的像素点先存入缓冲区,然后在屏幕上一次性显示出来。缓冲区它也是个容器。
  • 图像消失问题是因为组件重绘问题。
  • 除了接口,类里面也可以定义常量,常量可以直接通过类名来调用。

图像重绘问题:

  • 所有的swing包下的每一个组件都有一个paint方法,paint方法的作用:绘制组件本身。
  • swing包下的每一个组件都要通过调用paint函数把组件的效果显示在我们的屏幕上。
  • 当改变窗体的状态(隐藏,改变大小)都会导致窗体上所有的swing组件重新/自动调用paint方法。
  • 解决办法:让组件在重绘的过程中,把我们的图像显示效果也一起画一遍。
  • 解决图像重绘问题:1.重写组件的paint方法,添加paint方法绘制组件的功能
  •                                  2.保存图像数据
  • g.drawImage(img, x, x, width, height, observer) 
  •         img:画哪张图片  x,y画在哪个位置,图片的左上角    最后一个暂时用不到,给null

 三、代码实现

package com.gch.filterarithmetic;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
   滤镜算法
 */
public class PixelUI {
    /**
       图像处理界面
     */
    public void showUI(){
        JFrame win = new JFrame("PC版美颜相机");
        win.setSize(1000,650);
        win.setLocationRelativeTo(null);
        win.setDefaultCloseOperation(3);

        // 设置边框/边界布局:BorderLayout 用这种边框布局,一个方向只能加一个组件
        win.setLayout(new BorderLayout());

        // 面板对象/桌布:JPanel 面板对象的默认颜色和窗体同色
        // 功能区:eastPanel
        JPanel eastPanel = new JPanel();
        // 设置功能区面板对象的背景色
        eastPanel.setBackground(Color.yellow);
        // 设置功能区面板对象的大小
        eastPanel.setPreferredSize(new Dimension(120,0));
        // 把功能区面板对象添加到窗体上 并且设置功能区的位置
        win.add(eastPanel,BorderLayout.EAST);

        // 创建事件处理类对象
        ButtonMouse mouse = new ButtonMouse();

        // 功能区按钮的添加
        // 定义字符串数组保存功能区按钮的名称
        String[] functionButton = {"原图","马赛克","灰度","黑白","去色","单色","底片/反向","怀旧","褐色","连环画","冰冻",
                               "熔铸","浮雕","放大镜","左转","右转","撤回"};
        for(int i = 0;i < functionButton.length;i++){
            // 定义按钮添加
            JButton btn = new JButton(functionButton[i]);
            // 把按钮添加到功能区面板
            eastPanel.add(btn);
            // 给按钮添加动作监听器:绑定事件处理类
            btn.addActionListener(mouse);
        }

        // 自定义面板类:MyPanel
        // 图像显示区/内容显示区:drawPanel
        MyPanel drawPanel = new MyPanel();
        // 设置图像显示区的背景色
        drawPanel.setBackground(Color.LIGHT_GRAY);
        // 把图像显示区添加到窗体上并设置图像显示区的位置
        win.add(drawPanel, BorderLayout.CENTER);

        // 设置窗体显示可见
        win.setVisible(true);
        
        // 画笔更新,画笔的获取要在内容显示区,直接传内容显示区对象/面板对象
        mouse.setG(drawPanel);
    }
}
package com.gch.filterarithmetic;

import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;

/**
   自定义面板类:图像显示区/内容显示区
 */
public class MyPanel extends JPanel {
    // 定义缓冲区,保存传递过来的当前图像的缓冲对象
    private BufferedImage buff;
    /**
       定义set方法,初始化属性
     */
    public void setBuff(BufferedImage buff) {
        this.buff = buff;
    }
    /**
       重写绘制组件的paint方法
     */
    @Override
    public void paint(Graphics g){
        // 1.保留绘制组件本身的功能:调用父类的方法
        super.paint(g); // super:表示当前类的父类对象
        // 2.绘制当前的图像功能,把画好的缓冲区buff传递过来
        g.drawImage(buff, 0 , 0 , null);
    }
}
package com.gch.filterarithmetic;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
   事件处理类:给按钮添加动作监听器
 */
public class ButtonMouse implements ActionListener {
    // 定义保存当前图像的缓冲区
    private BufferedImage buff;
    /**
       定义get方法,获取属性
     */
    public BufferedImage getBuff() {
        return buff;
    }
    // 定义缓冲区数组,保存图层的数组
    private BufferedImage[] buffArr = new   BufferedImage[100];
    // 定义操作数组的下标
    private int index = 0;
    // 保存当前的有效图层
    private int count = 0;
    // 标记位
    public int flag = 1;
    // 定义图像显示区/内容显示区对象
    private MyPanel drawPanel;
    // 定义画笔对象,保存传递过来的画笔对象
    private Graphics g;
    /**
       定义set方法,初始化属性
     */
    public void setG(MyPanel drawPanel) {
        this.drawPanel = drawPanel;
    }

    /**
       事件处理方法:动作监听器方法
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        //每次画之前重新获取画笔,可以让画笔的获取实时更新
        g = drawPanel.getGraphics();

        // 指定图片路径
        String path = "C:\\Users\\A.G.H\\Pictures\\Camera Roll\\t0118a001acf2c4dc77.jpg";
        // 把指定路径的图片转换为int型的二维数组,获取指定图片路径的像素点的像素值
        int[][] pixelArr = getImagePixel(path);
        // 获取按钮上的内容
        String buttonName = e.getActionCommand();
        // 根据不同的按钮选择来实现不同的滤镜算法
        switch (buttonName){
            case "原图":
                masterPixel(pixelArr);
                break;
            case "马赛克":
                mosaicPixel(pixelArr);
                break;
            case "灰度":
                grayPixel(pixelArr);
                break;
            case "黑白":
                blackWhitePixel(pixelArr);
                break;
            case "去色":
                desaturatePixel(pixelArr);
                break;
            case "单色":
                singleColorPixel(pixelArr);
                break;
            case "底片/反向":
                artworkPixel(pixelArr);
                break;
            case "怀旧":
                retroPixel(pixelArr);
                break;
            case "褐色":
                brownPixel(pixelArr);
                break;
            case "连环画":
                comicsPixel(pixelArr);
                break;
            case "冰冻":
                freezePixel(pixelArr);
                break;
            case "熔铸":
                castingPixel(pixelArr);
                break;
            case "浮雕":
                reliefPixel(pixelArr);
                break;
            case "放大镜":
                enlargePixel(pixelArr);
                break;
            case "左转":
                leftPixel(pixelArr);
                break;
            case "右转":
                rightPixel(pixelArr);
                break;
        }

        if("撤回".equals(buttonName)) {
            //取出最后一个图层
            //把当前图层更新为撤回的图层
            buff = buffArr[--count];
            index = count;
            System.out.println("buff=" +buff + "count="+count);
        }else {
            //保存当前图层
            buffArr[index] = buff; //每按一次按钮就保存一次
            count = index; //记录有效图层
            index++;
            System.out.println("index="+index);
        }
        //更新缓冲区对象后再把当前缓冲区传递给自定义类MyPanel
        drawPanel.setBuff(buff); //每更新一次就传一次
        //刷新面板
        drawPanel.repaint();
    }
    /**将图片转换为int型的二维数组,获取图片像素的宽高,获取每个像素点的像素值
     * 获取指定路径图片的像素点的像素值
     * @param path:指定图片路径
     * @return:返回保存指定路径图片像素点的像素值的二维数组
     */
    public int[][] getImagePixel(String path){
        // 创建文件对象
        File file = new File(path);
        // BufferedImage:图像缓冲区,图片数据的封装类
        BufferedImage bufferedImage = null;
        // 用输入流读取指定文件的数据
        try {
            bufferedImage = ImageIO.read(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        // 获取图片像素的宽高
        int w = bufferedImage.getWidth(); // 宽:对应二维数组的列
        int h = bufferedImage.getHeight(); // 高:对应二维数组的行
        // 保存到二维数组
        int[][] pixelArr = new int[h][w];
        // 遍历二维数组的每一个元素,通过双层循环遍历整个图片的像素点
        for(int i = 0;i < h;i++){
            for(int j = 0;j < w;j++){
                // 通过图像缓冲区bufferedImage对象的getRGB()方法获取每个像素点的像素值
                int pixel = bufferedImage.getRGB(j, i);
                // 把每个像素点的像素值保存到二维数组中
                pixelArr[i][j] = pixel;
            }
        }
        // 返回保存指定图片像素点的像素值的二维数组
        return pixelArr;
    }

    /**
     * 原图效果
     * @param pixelArr:保存图片像素点的像素值的二维数组
     */
    public void masterPixel(int[][]pixelArr) {
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //把像素点存到缓冲区里      缓冲区它也是个容器
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出所有的像素值
                int pixel =pixelArr[i][j];
                //把像素值转为Color对象
                Color color  = new Color(pixel);
                //把所有的像素点画在缓冲区里面
                //把画笔设置成当前颜色
                buffG.setColor(color);
                //绘制出当前颜色的像素点
                buffG.fillRect(j, i, 1, 1);
            }
        }
        //把图片显示在窗体上  缓冲区是个组件,如果你不把它显示出来,根本就看不见,缓冲区它是个图片  缓冲区/缓存图片
        g.drawImage(buff, 0, 0,null);   //drawImage方法它重载了好多次
    }

    /**
       马赛克效果:在固定范围内放大像素点
     */
    public void mosaicPixel(int[][]pixelArr) {
        //创建缓冲区的对象 BufferedImage buff = new  BufferedImage(width, height, imageType)   常量,可以直接通过类名来调用
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i+=10) {   //放大了几倍,就跳过几个像素
            for(int j=0;j<pixelArr[i].length;j+=10) {
                //取出图片的所有像素值
                int  pixel =  pixelArr[i][j];
                //把像素值转为Color对象
                Color color = new Color(pixel);
                //把画笔对象设置成当前颜色
                buffG.setColor(color);
                //绘制出当前颜色的像素点   因为每一个像素点的位置是不一样的
                buffG.fillRect(j, i, 10, 10);  //放大了10倍数
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       灰度效果
    */
    public void grayPixel(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出所有的像素值
                int pixel = pixelArr[i][j];
                //把像素值转为Color对象
                Color color = new Color(pixel);
                //取RGB平均值,则画成灰度图
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                int ave = (red+green+blue)/3;
                //把平均值作为三原色的基础值
                Color nc = new Color(ave,ave,ave);
                buffG.setColor(nc);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }
    //2.通过将像素值右移得到RGB三原色的分量值
    public void drawPixel4(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[0].length;j++) {
                //取出所有的像素值
                int pixel = pixelArr[i][j];
                //通过右移取出pixel像素中的三原色
                int red = (pixel>>16)&0xFF;  //位运算:只有1&1=1
                int green = (pixel>>8)&0xFF;
                int blue = (pixel>>0)&0xFF;
                //取RGB平均值
                int ave = (red+green+blue)/3;
                //把平均值作为三原色的初始值
                Color nc = new Color(ave,ave,ave);
                buffG.setColor(nc);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }
    //3.取三种颜色的最大值来实现灰度滤镜
    public void drawPixel5(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出所有的像素值
                int pixel = pixelArr[i][j];
                //通过将像素值右移得到RGB三原色分量值
                int red  = (pixel>>16)&0xFF;
                int green =(pixel>>8)&0xFF;
                int blue =(pixel>>0)&0xFF;
                int tempmax = Math.max(red, green);     //int tempmax = (red>green)?red:green;
                int max =Math.max(tempmax, blue);		//int max = (tempmax>blue)?tempmax:blue;
                //把三种颜色最大值作为三原色的初始值
                Color nc = new Color(max,max,max);
                //把画笔设置成当前颜色
                buffG.setColor(nc);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }
    //4.取三种颜色的最小值来实现灰度滤镜
    public void drawPixel6(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[0].length;j++) {
                //取出所有的像素值
                int pixel = pixelArr[i][j];
                //通过将像素值右移得到RGB三原色分量值
                int red = (pixel>>16)&0xFF;
                int green =(pixel>>8)&0xFF;
                int blue =(pixel>>0)&0xFF;
                int tempmin = Math.min(red, green);      //int tempmin = (red<green)?red:green;
                int min = Math.min(tempmin, blue);   	  //int min =(tempmin<blue)?tempmin:blue;
                //把三原色的最小值作为RGB三原色的初始值
                Color color = new Color(min,min,min);
                buffG.setColor(color);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff,0, 0, null);
    }

    /**
       黑白滤镜
     */
    public void blackWhitePixel(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                int pixel = pixelArr[i][j];
                //通过将像素值右移得到RGB三原色的分量值
                int red = (pixel>>16)&0xFF;
                int green =(pixel>>8)&0xFF;
                int blue = (pixel>>0)&0xFF;
                //计算RGB三原色平均值
                int ave = (red+green+blue)/3;
                if(ave>=100) {
                    ave = 255;
                }else {
                    ave = 0;
                }
                //将ave设为RGB三原色初始值
                Color color = new Color(ave,ave,ave);
                buffG.setColor(color);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       去色滤镜
     */
    public void desaturatePixel(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出所有的像素值
                int pixel = pixelArr[i][j];
                //把像素值右移得到RGB三原色分量值
                int red = (pixel>>16)&0xFF;
                int green =(pixel>>8)&0xFF;
                int blue = (pixel>>0)&0xFF;
                //取RGB三原色的最大值
                int tempmax = Math.max(red, green);
                int max = Math.max(tempmax, blue);
                //取RGB三原色的最小值
                int tempmin =Math.min(red, green);
                int min =Math.min(tempmin, blue);
                //取RGB三原色最大值和最小值的平均值
                int ave = (max+min)/2;
                //把平均值设为RGB三原色的初始值
                Color color = new Color(ave,ave,ave);
                buffG.setColor(color);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       单色滤镜
     */
    public void singleColorPixel(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出所有的像素点
                int pixel = pixelArr[i][j];
                //把像素点转为Color对象
                Color color = new Color(pixel);
                //获取RGB三原色分量值
                int red = color.getRed();
                int green = color.getGreen();
                int blue = color.getBlue();
                //只保留一个颜色
                Color nc = new Color(red,0,0);
                buffG.setColor(nc);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff,0,0, null);
    }

    /**
       底片/反向滤镜
     */
    public void artworkPixel(int [][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出所有的像素值
                int pixel = pixelArr[i][j];
                //把像素值右移得到RGB三原色的分量值
                int red = 255 -(pixel>>16)&0xFF;
                int green = 255-(pixel>>8)&0xFF;
                int blue = 255 -(pixel>>0)&0xFF;
                //把分量值设为RGB三原色初始值
                Color color = new Color(red,green,blue);
                buffG.setColor(color);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       怀旧滤镜
     */
    public void retroPixel(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出所有的像素值
                int pixel =pixelArr[i][j];
                //把像素值右移得到RGB三原色分量值
                int red = (pixel>>16)&0xFF;
                ///  System.out.println("red="+red);
                int green = (pixel>>8)&0xFF;
                //  System.out.println("green="+green);
                int blue =(pixel>>0)&0xFF;
                // System.out.println("blue="+blue);
                int R = (int)(0.393*red+0.769*green+0.189*blue);
                if(R>255) {
                    R=255;
                }
                // System.out.println("R="+R);
                int G = (int)(0.349*red+0.686*green+0.168*blue);
                if(G>255) {
                    G=255;
                }
                //System.out.println("G="+G);
                int B = (int)(0.272*red+0.534*green+0.131*blue);
                if(B>255) {
                    B=255;
                }
                //System.out.println("B="+B);
                //把新的RGB值设为RGB三原色
                Color color = new Color(R,G,B);
                buffG.setColor(color);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       褐色滤镜
     */
    public void brownPixel(int pixelArr[][]) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[0].length;j++) {
                int pixel = pixelArr[i][j];
                int red = (pixel>>16)&0xFF;
                int green = (pixel>>8)&0xFF;
                int blue = (pixel>>0)&0xFF;
                //褐色滤镜算法
                red = (int)(red*0.393+green*0.769+blue*0.189);
                if(red>255) {
                    red=255;
                }
                green = (int)(red*0.349+green*0.686+blue*0.168);
                if(green>255) {
                    green=255;
                }
                blue = (int)(red*0.272+green*0.534+blue*0.131);
                if(blue>255) {
                    blue = 255;
                }
                //把新的RGB值设为三原色初始值
                Color color = new Color(red,green,blue);
                buffG.setColor(color);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       连环画滤镜
     */
    public void comicsPixel(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出所有的像素点
                int pixel = pixelArr[i][j];
                int R = (pixel>>16)&0xFF;
                int G = (pixel>>8)&0xFF;
                int B = (pixel>>0)&0xFF;
                R = Math.abs(G-B+G+R)*R/256;
                if(R>255) {
                    R=255;
                }
                G = Math.abs(B-G+B+R)*R/256;
                if(G>255) {
                    G=255;
                }
                B = Math.abs(B-G+B+R)*G/256;
                if(B>255) {
                    B=255;
                }
                Color color = new Color(R,G,B);
                buffG.setColor(color);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       冰冻滤镜
     */
    public void freezePixel(int pixelArr[][]) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[i].length;j++) {
                int pixel = pixelArr[i][j];
                int R = (pixel>>16)&0xFF;
                int G = (pixel>>8)&0xFF;
                int B = (pixel>>0)&0xFF;
                R = (R-G-B)*3/2;
                if(R<0) {
                    R=0;
                }else if(R>255) {
                    R=255;
                }
                //System.out.println("R="+R);
                G = (G-R-B)*3/2;
                if(G<0) {
                    G=0;
                }else if(G>255) {
                    G=255;
                }
                // System.out.println("G="+G);
                B = (B-G-R)*3/2;
                if(B<0) {
                    B=0;
                }else if(B>255) {
                    B=255;
                }
                //	 System.out.println("B="+B);
                Color color = new Color(R,G,B);
                buffG.setColor(color);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       熔铸滤镜
     */
    public void castingPixel(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {
            for(int j=0;j<pixelArr[0].length;j++) {
                int pixel = pixelArr[i][j];
                int R = (pixel>>16)&0xFF;
                int G = (pixel>>8)&0xFF;
                int B = (pixel>>0)&0xFF;
                R = R*128/(G+B+1);
                if(R<0) {
                    R=0;
                }else if(R>255){
                    R =255;
                }
                G = G*128/(R+B+1);
                if(G<0) {
                    G=0;
                }else if(G>255) {
                    G=255;
                }
                B = B*128/(G+R+1);
                if(B<0) {
                    B=0;
                }else if(B>255) {
                    B=255;
                }
                //
                Color color = new Color(R,G,B);
                buffG.setColor(color);
                buffG.fillRect(j, i,1,1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       浮雕效果
     */
    public void reliefPixel(int[][]pixelArr) {
        //创建缓冲区对象
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        //2.获取缓冲区的画笔对象   buffG缓冲画笔  把像素点画到缓冲区里面
        Graphics  buffG =  buff.getGraphics();
        for(int i =0;i<pixelArr.length-1;i++) {
            for(int j=0;j<pixelArr[0].length-1;j++) {
                int pixel0 = pixelArr[i][j];
                Color color0 = new Color(pixel0);
                int R0 =  color0.getRed();
                int G0 = color0.getGreen();
                int B0 = color0.getBlue();

                int pixel1 = pixelArr[i+1][j+1];
                Color color1 = new Color(pixel1);
                int R1 = color1.getRed();
                int G1 = color1.getGreen();
                int B1 = color1.getBlue();

                int NR = R0-R1+128;
                if(NR<0) {
                    NR = 0;
                }else if(NR>255){
                    NR = 255;
                }
                int NG = G0-G1+128;
                if(NG<0) {
                    NG = 0;
                }else if(NG>255) {
                    NG = 255;
                }
                int NB = B0-B1+128;
                if(NB<0) {
                    NB = 0;
                }else if(NB>255) {
                    NB = 255;
                }

                Color nc = new Color(NR,NG,NB);
                buffG.setColor(nc);
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 0, 0, null);
    }

    /**
       放大镜
     */
    public void enlargePixel(int[][]pixelArr) {
        buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
        Graphics  buffG =  buff.getGraphics();
        for(int i=0;i<pixelArr.length;i++) {   //放大了几倍,就跳过几个像素
            for(int j=0;j<pixelArr[i].length;j++) {
                //取出图片的所有像素值
                int  pixel =  pixelArr[i][j];
                //把像素值转为Color对象
                Color color = new Color(pixel);
                //把画笔对象设置成当前颜色
                buffG.setColor(color);
                //绘制出当前颜色的像素点   因为每一个像素点的位置是不一样的
                buffG.fillRect(j, i, 1, 1);  //放大了10倍数
            }
        }                                 //同比例缩放
        g.drawImage(buff, 0, 0,pixelArr[0].length+220, pixelArr.length+220, null);
    }

    /**
       左转90°
     */
    public int[][] leftPixel(int[][]pixelArr) {
        //新建数组
        int [][] newArr = {};
        //第一次旋转   现在的行是原来列数的最大索引-原来的列    现在的列是原来的行
        if(flag%4 == 1) {
            //创建缓冲区对象
            buff = new  BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
            //新建数组的大小
            newArr = new int[pixelArr[0].length][pixelArr.length];
            for(int i = 0;i < pixelArr.length;i++ ) {
                for(int j = 0;j < pixelArr[0].length;j++) {
                    newArr[pixelArr[0].length-1-j][i]  =  pixelArr[i][j];
                }
            }
            flag++;
        }

        //第二次旋转   现在的行是原来的行   现在的列是原来列的最大索引-列
        else  if(flag%4 == 2) {
            buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
            newArr = new int[pixelArr.length][pixelArr[0].length];
            for(int i = 0;i < pixelArr.length;i++) {
                for(int j = 0;j < pixelArr[0].length;j++) {
                    newArr[i][pixelArr[0].length-1-j] = pixelArr[i][j];
                }
            }
            flag++;
        }

        //第三次旋转  现在的行是原来的列   现在的列是原来的行
        else  if(flag%4 == 3) {
            buff = new  BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
            newArr = new int[pixelArr[0].length][pixelArr.length];
            for(int i = 0;i < pixelArr.length;i++) {
                for(int j = 0;j < pixelArr[0].length;j++) {
                    newArr[j][i] = pixelArr[i][j];
                }
            }
            flag++;
        }

        //第四次旋转
        else if(flag%4 == 0) {
            buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
            newArr = pixelArr;
            flag++;
        }

        //获取缓冲区的画笔对象
        Graphics  buffG =  buff.getGraphics();

        for(int i = 0;i < newArr.length;i++) {
            for(int j = 0;j < newArr[0].length;j++) {
                //取出所有的像素值
                int pixel = newArr[i][j];
                //把像素值转为Color对象
                Color color = new Color(pixel);
                //把缓冲画笔设置成当前颜色
                buffG.setColor(color);
                //绘制出当前颜色的像素点
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff,100,100,null);
        return newArr;
    }

    /**
       右转90°
     */
    public int[][] rightPixel(int[][]pixelArr){
        //新建数组
        int [][] newArr = {} ;

        //第一次旋转  现在的行是原来的列  现在的列是原来行数的最大索引-原来的行
        if(flag%4 == 1) {
            //创建缓冲区对象
            buff = new  BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB);
            //新建数组的大小
            newArr = new int[pixelArr[0].length][pixelArr.length];
            for(int i = 0;i < pixelArr.length;i++ ) {
                for(int j = 0;j < pixelArr[0].length;j++) {
                    newArr[j][pixelArr.length-1-i]  =  pixelArr[i][j];
                }
            }
            flag++;
        }

        //第二次旋转  现在的行是原来行的最大索引-行   现在的列是原来列的最大索引-列
        else  if(flag%4 == 2) {
            buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);
            newArr = new int[pixelArr.length][pixelArr[0].length];
            for(int i = 0;i < pixelArr.length;i++) {
                for(int j = 0;j < pixelArr[0].length;j++) {
                    newArr[pixelArr.length-1-i][pixelArr[0].length-1-j] = pixelArr[i][j];
                }
            }
            flag++;
        }

        //第三次旋转       现在的行是原来列的最大索引-列  现在的列是原来的行
        else  if(flag%4 == 3) {
            buff = new  BufferedImage(pixelArr.length, pixelArr[0].length, BufferedImage.TYPE_INT_RGB);


            newArr = new int[pixelArr[0].length][pixelArr.length];
            for(int i = 0;i < pixelArr.length;i++) {
                for(int j = 0;j < pixelArr[0].length;j++) {
                    newArr[pixelArr[0].length-1-j][i] = pixelArr[i][j];
                }
            }
            flag++;
        }

        //第四次旋转
        else if(flag%4 == 0) {
            buff = new  BufferedImage(pixelArr[0].length, pixelArr.length, BufferedImage.TYPE_INT_RGB);

            newArr = pixelArr;
            flag++;
        }
        //获取缓冲区的画笔对象
        Graphics  buffG =  buff.getGraphics();

        //遍历并画出像素点
        for(int i = 0;i < newArr.length;i++) {
            for(int j = 0;j < newArr[0].length;j++) {
                //取出所有的像素值
                int pixel = newArr[i][j];
                //把像素值转为Color对象
                Color color = new Color(pixel);
                //把缓冲画笔设置成当前颜色
                buffG.setColor(color);
                //绘制出当前颜色的像素点
                buffG.fillRect(j, i, 1, 1);
            }
        }
        g.drawImage(buff, 100, 100, null);
        return newArr;
    }

}
package com.gch.filterarithmetic;

public class Manage {
    /**
       主函数
     */
    public static void main(String[] args) {
        PixelUI ui = new PixelUI();
        ui.showUI();
    }
}

四、效果图

 

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Surpass余sheng军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值