Java图片处理-通过按钮监听实现多种滤镜效果

图片有许多种滤镜效果,那如何在不更改代码的情况下,通过点击窗体上的按钮将自己想要的滤镜效果绘制在窗体上呢?很简单,即通过安装监听器,实现每个按钮都能动作监听。这需要我们创建三个类——图片处理界面类、图片按钮选择监听器类、图片处理效果类。

图片处理界面类

-创建一个初始化界面

public void init() {
        JFrame jf=new JFrame();
		jf.setTitle("图形图像处理");
		jf.setSize(800,800);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jf.setLocationRelativeTo(null);//窗体位置居中
		//设置布局
		FlowLayout flow=new FlowLayout();
		jf.setLayout(flow);
		jf.setVisible(true);//添加组件后可视化
}

-添加监听器 创建监听器对象

-获取Graphics(绘图类) 传入监听器中

imglisten.g=jf.getGraphics();

- 创建函数方法,批量循环完成多个按钮的创建、添加与监听器加载,减少代码重用

public void addButton() {
		String[] btnstrs= {"原图","反片","脸部提亮","马赛克","美白","轮廓提取","灰度","二值化","油画","图片融合","撤回"};//定义一个字符串数组 存储所有按钮的字符串
		for(int i=0;i<btnstrs.length;i++) {
			String btnstr=btnstrs[i];
			//窗体添加按钮
			JButton btn=new JButton(btnstr);
			this.add(btn);
			//按钮添加监听器对象
			btn.addActionListener(imglisten);
		}
	}

完整代码:

import java.awt.*;
import javax.swing.*;
public class Imagepad extends JFrame {
	private static final long serialVersionUID = 1L;
	//创建监听器对象
	ImageListener imglisten=new ImageListener();
	public void init() {
		this.setTitle("图形图像处理");
		this.setSize(800,800);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setLocationRelativeTo(null);//窗体位置居中
		//设置布局
		FlowLayout flow=new FlowLayout();
		setLayout(flow);
		addButton();//调用函数
		//获取Graphics对象  传给监听器中的Gaphics 类型属性变量名
		this.setVisible(true);//添加组件后可视化
		imglisten.g=this.getGraphics();//在可视化之后,在窗体上获取,赋值给监听器对象
	}
	/**
	 * 创建函数方法
	 * 批量循环完成多个按钮的创建、添加与监听器加载,减少代码重用
	 */
	public void addButton() {
		String[] btnstrs= {"原图","反片","脸部提亮","马赛克","美白","轮廓提取","灰度","二值化","油画","图片融合","撤回"};//定义一个字符串数组 存储所有按钮的字符串
		for(int i=0;i<btnstrs.length;i++) {
			String btnstr=btnstrs[i];
			//窗体添加按钮
			JButton btn=new JButton(btnstr);
			this.add(btn);
			//按钮添加监听器对象
			btn.addActionListener(imglisten);
		}
	}
	public static void main(String[]args) {
		Imagepad imagepad=new Imagepad();
		imagepad.init();
	}


}

图片按钮选择监听器类

-实现动作监听器 implements ActionListener

-创建图片处理效果类对象

-创建ImageListener(){}方法,定义图片路径,得到图片的二维数组

public ImageListener() {
		//定义给定图片的路径
		String imgpath01="C:\\Users\\31491\\Pictures\\toux.jpg";
		String imgpath02="C:\\Users\\31491\\Pictures\\ziji1.jpg";
		String imgpath03="C:\\Users\\31491\\Pictures\\ziji2.jpg";
		String imgpath04="C:\\Users\\31491\\Pictures\\bear.jpg";
		//数组初始化
		imgarr=imgeff.getimagepixelarry(imgpath01);
		imgarr1 = imgeff.getimagepixelarry(imgpath01);
		imgarr2=imgeff.getimagepixelarry(imgpath04);
	}

- 重写监听器的方法 actionPerformed(ActionEvent e){}

- 在方法中可以获取按钮上的字符串

- 通过字符串 选择使用哪种滤镜来绘制图片

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class ImageListener implements ActionListener {
	Graphics g=null;//定义图像类变量名,在窗体上获取
	ImageEff imgeff=new ImageEff();//创建图像处理滤镜类对象
	int[][] imgarr= {};
	int[][] imgarr1= {};
	int[][] imgarr2= {};//定义存储当前操作的图片的像素值数组
	/*
	 *  构造方法 创建对象调用 适合在其中写初始化的代码
	 */
	public ImageListener() {
		//定义给定图片的路径
		String imgpath01="C:\\Users\\31491\\Pictures\\toux.jpg";
		String imgpath02="C:\\Users\\31491\\Pictures\\ziji1.jpg";
		String imgpath03="C:\\Users\\31491\\Pictures\\ziji2.jpg";
		String imgpath04="C:\\Users\\31491\\Pictures\\bear.jpg";
		//数组初始化
		imgarr=imgeff.getimagepixelarry(imgpath01);
		imgarr1 = imgeff.getimagepixelarry(imgpath01);
		imgarr2=imgeff.getimagepixelarry(imgpath04);
	}
	/*
	 * 点击按钮时调用
	 */
	//"原图","反片","脸部提亮","马赛克","美白","轮廓提取","灰度","二值化","油画","图片融合","撤回"
	public void actionPerformed(ActionEvent e) {
		String btnstr=e.getActionCommand();//获取按钮上的字符串
		System.out.println("点击了"+btnstr);
		if(btnstr.equals("原图")) {
			imgeff.drawimage01(imgarr,g);
		}else if(btnstr.equals("反片")) {
			imgeff.drawimage02(imgarr,g);
		}else if(btnstr.equals("脸部提亮")) {
			imgeff.drawimage03(imgarr,g);
		}else if(btnstr.equals("马赛克")) {
			imgeff.drawimage04(imgarr,g);
		}else if(btnstr.equals("美白")) {
			imgeff.drawimage05(imgarr,g);
		}else if(btnstr.equals("轮廓提取")) {
			imgeff.drawimage06(imgarr,g);
		}else if(btnstr.equals("灰度")) {
			imgeff.drawimage07(imgarr,g);
		}else if(btnstr.equals("二值化")) {
			imgeff.drawimage08(imgarr,g);
		}else if(btnstr.equals("油画")) {
			imgeff.drawimage09(imgarr,g);
		}else if(btnstr.equals("图片融合")) {
			imgeff.drawimage10(imgarr1,imgarr2,g);
		}else if(btnstr.equals("撤回")) {
			imgeff.drawimage11(imgarr,g);
		}
	}

}


图片处理效果类

- 将图片转为二维数组

public int[][] getimagepixelarry(String path) {
		File file=new File(path);//将图片保存为文件
		BufferedImage buffimg=null;//声明BufferedImage类型变量名
			try {
				buffimg=ImageIO.read(file);
			} catch (IOException e) {
				e.printStackTrace();
			}
			//获取图片的宽高
			int w=buffimg.getWidth();
			int h=buffimg.getHeight();
			int[][] imgarr=new int[w][h];
			//将图片的像素值保存到数组中
			for(int i=0;i<w;i++) {
				for(int j=0;j<h;j++) {
					imgarr[i][j]=buffimg.getRGB(i, j);
				}
			}
			return imgarr;
	}

- 提供滤镜处理方法

1原图

public void drawimage01(int[][]imgarr,Graphics g) {
		for(int i=0;i<imgarr.length;i++) {
			for(int j=0;j<imgarr[i].length;j++) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				g.setColor(color);
				g.fillRect(200+i,200+j,1,1);
			}
		}
	}

 2反片

r=255-color.getRed();  g=255-color.getGreen();  b=255-color.getBlue()

public void drawimage02(int[][] imgarr, Graphics g) {
		for(int i=0;i<imgarr.length;i++) {
			for(int j=0;j<imgarr[i].length;j++) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				int red=255-color.getRed();
				int green=255-color.getGreen();
				int blue=255-color.getBlue();
				Color ncolor=new Color(red,green,blue);
				g.setColor(ncolor);
				g.fillRect(200+i, 200+j, 1, 1);
			}
		}	
	}

 

3脸部提亮

若图片颜色的r、g、b值大于220,则令新的画笔颜色r、g、b值为250,否则则令新的画笔颜色r、g、b在原有的基础上加30。若原有图片(r+b+g)/3小于等于100,则将画笔颜色设置为原有图片的颜色,否则则将画笔颜色设置为新的画笔颜色。

public void drawimage03(int[][] imgarr, Graphics g) {
		for(int i=0;i<imgarr.length;i++) {
			for(int j=0;j<imgarr[i].length;j++) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				int red=color.getRed();
				int green=color.getGreen();
				int blue=color.getBlue();
				int gray=(red+green+blue)/3;
				int nred=red>220? 250:red+30;
				int ngreen=green>220? 250:green+30;
				int nblue=blue>220? 250:blue+30;
				Color ncolor=new Color(nred,ngreen,nblue);
				if(gray<=100) {
					g.setColor(color);
				}else {
					g.setColor(ncolor);
				}
		
		        g.fillRect(200+i, 200+j, 1, 1);
			}
		}	
	}

 

4马赛克

将每个像素值放大一定数量

public void drawimage04(int[][] imgarr, Graphics g) {
		for(int i=0;i<imgarr.length;i+=15) {
			for(int j=0;j<imgarr[i].length;j+=15) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				g.setColor(color);
				g.fillRect(200+i,200+j,15,15);
			}
		}
}

5美白

将原有图片颜色的r、g、b值在一定范围内放大,使放大的r、g、b值不超过255就可以

public void drawimage05(int[][] imgarr, Graphics g) {
		for(int i=0;i<imgarr.length;i++) {
			for(int j=0;j<imgarr[i].length;j++) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				int red=color.getRed();
				int green=color.getGreen();
				int blue=color.getBlue();
				int nred=red+30>255? 255:red+30;
				int ngreen=green+30>255? 255:green+30;
				int nblue=blue+30>255? 255:blue+30;
				Color ncolor=new Color(nred,ngreen,nblue);
				g.setColor(ncolor);
				g.fillRect(200+i,200+j,1,1);
			}
		}
		
	}

6轮廓提取

图像轮廓处颜色值会发生较大的变化,要提取图像轮廓,则需比较轮廓处某点的颜色灰度值和其周围某点颜色灰度值。若两点之差的绝对值大于一定值时将画笔颜色设置为黑色,否则则将画笔颜色设置为白色。

public void drawimage06(int[][] imgarr, Graphics g) {
		for(int i=0;i<imgarr.length-2;i++) {
			for(int j=0;j<imgarr[i].length-2;j++) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				int red=color.getRed();
				int green=color.getGreen();
				int blue=color.getBlue();
				int gray=(red+green+blue)/3;
				int nrgb=imgarr[i+2][j+2];
				Color ncolor=new Color(nrgb);
				int nred=ncolor.getRed();
				int ngreen=ncolor.getGreen();
				int nblue=ncolor.getBlue();
				int ngray=(nred+ngreen+nblue)/3;
				if(Math.abs(gray-ngray)>15) {
					g.setColor(Color.black);
				}else {
					g.setColor(Color.white);
				}
				g.fillRect(200+i, 200+j, 1, 1);
					
			}
		}		
	}

 

7灰度

-平均值法

nr=ng=nb=gray=(r+g+b)/3

-按一定比例(红色占比稍多些)

nr=ng=nb=gray=(r*0.41+g*0.36+b*0.23)

public void drawimage07(int[][] imgarr, Graphics g) {
		for(int i=0;i<imgarr.length;i++) {
			for(int j=0;j<imgarr[i].length;j++) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				int red=color.getRed();
				int green=color.getGreen();
				int blue=color.getBlue();
				int gray=(red+green+blue)/3;
				Color ncolor=new Color(gray,gray,gray);
				g.setColor(ncolor);
				g.fillRect(200+i, 200+j, 1, 1);
			}
		}
		
	}

 

8二值化

新得到的图片只有两种颜色,即黑色与白色。若图片颜色的灰度值小于一定值,则将画笔颜色设置为黑、白的其中一种颜色,否则则将画笔颜色设置为剩下的一种颜色。

public void drawimage08(int[][] imgarr, Graphics g) {
		for(int i=0;i<imgarr.length;i++) {
			for(int j=0;j<imgarr[i].length;j++) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				int red=color.getRed();
				int green=color.getGreen();
				int blue=color.getBlue();
				int gray=(red+green+blue)/3;
				if(gray<=100) {
					Color ncolor=new Color(0,0,0);
					g.setColor(ncolor);
					g.fillRect(200+i,200+j,1,1);
				}else {
					Color ncolor=new Color(255,255,255);
					g.setColor(ncolor);
					g.fillRect(200+i,200+j,1,1);
				}
			}
		}	
	}

 

9油画

将原有图片的像素值扩大一定数量,且每个像素点不再是一个个小矩形,而是不等大小的圆,圆的外切矩形的长宽是随机值。

public void drawimage09(int[][] imgarr, Graphics g) {
		for(int i=0;i<imgarr.length;i+=5) {
			for(int j=0;j<imgarr[i].length;j+=5) {
				int rgb=imgarr[i][j];
				Color color=new Color(rgb);
				Random random=new Random();
				int r=random.nextInt(15)+5;
				g.setColor(color);
				g.fillOval(200+i, 200+j, r, r);
			}
		}	
	}

 

10图片融合

将多张图片按一定方式组合,则先需调整图片大小和比例,然后将多张图片转为二维数组,接着设置画笔颜色值,将多张图片的画笔起点设置在不同地方。

public void drawimage10(int[][] imgarr1,int[][] imgarr2, Graphics g) {
		for(int i=0;i<imgarr1.length;i++) {
			for(int j=0;j<imgarr1[i].length;j++) {
				int rgb=imgarr1[i][j];
				Color color=new Color(rgb);
				g.setColor(color);
				g.fillRect(200+i, 200+j, 1, 1);
			}
		}
		for(int i=0;i<imgarr2.length;i++) {
			for(int j=0;j<imgarr2[i].length;j++) {
				int rgb=imgarr2[i][j];
				Color color=new Color(rgb);
				g.setColor(color);
				g.fillRect(208+i, 270+j, 1, 1);
			}
		}
					
	}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值