基于Java的图片效果处理

        该程序可以实现图片的模糊处理、灰度处理、二值化处理等功能,和美颜相机比较相似。还可以为图片添加马赛克。

        一张图片的形成是由各种颜色的像素块拼在一起所呈现出来的。我们需要列出每个点的像素值,并为其填充相应的颜色。因此,对于一副图像,可以看做其宽w*高h的一个二维数组,即图像=int[w][h],在w和h位置的每个int值,就是这个点的像素值。

图像处理的本质:对代表图像二维数组中的值进行重新计算。

一、点击添加图片按钮,在画布中画出一个圆点       

 首先,我们先写一个简单的程序,在画布中画一个点。步骤如下:

                1.创建一个tuxiang类,利用extends继承JFrame类;

                2.编写JFrame中固定程序,使之呈现出一个画布;

                3.为画布添加按钮及监听器;

                4.创建监听器类,编写按下按钮后所需实现的功能的代码。

        代码及结果示例如下:

//1.0 在界面中画出一个点

package TuXiang1;

import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;

	public class tuxiang1 extends JFrame {
		public void initUI(){
			this.setSize(450,450);
			this.setTitle("图像处理");
			this.setDefaultCloseOperation(3);
			this.setVisible(true);	
			FlowLayout fl = new FlowLayout();
			this.setLayout(fl);
			//加上按钮
			JButton buDraw = new JButton("添加图片");
			this.add(buDraw);
			//加监听器
			this.setVisible(true);
			//获取画布,一定在界面可见之后
			Graphics g = this.getGraphics();
			DrawLis1 dl = new DrawLis1(g);
			buDraw.addActionListener(dl);
		}
		
public static void main(String[] args) {
	tuxiang1 lu=new tuxiang1();
	lu.initUI();
	}
}
package TuXiang1;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;

//画图按钮的监听器,点一下画个东西出来
public class DrawLis1 implements ActionListener{
	
	private Graphics g;
	
	public DrawLis1(Graphics g) {
		this.g=g;
	}

		public void actionPerformed(ActionEvent e) {
			System.out.println("dssssss");
		g.fillOval(170,160,100,100); //(横坐标,纵坐标,宽,高)
		}
}

        此程序只实现了在画布中画一个点。如果要添加图片,先在项目文件中存入一张图片,利用监听器,将图片转换成二维数组,一个点一个点的在界面上显示出来。其中用到了java.awt.Color类,可以实现一切数字和颜色之间的转换操作;

二、将图片文件载入图片缓冲区,利用二维数组,将图片画在画布上

主函数tuxiang类不变,在监听器类中实现像素值的存储以及颜色的填充。监听器程序如下:

package TuXiang1;

import javax.imageio.ImageIO;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;

//画图按钮的监听器,点一下画个图像出来
public class DrawLis2 implements ActionListener{
	
	private Graphics g;
	public DrawLis2(Graphics g) {this.g=g;}
	public void actionPerformed(ActionEvent e) {
        
//改为画上一张图片
		int[][] ia = getImage();
		for(int i=0;i<ia.length;i++) { //下一个像素点的坐标
			for(int j=0;j<ia[i].length;j++) { //下一个像素点的坐标
				//取得一个int代表当前位置的像素值
				int v= ia[i][j];
			//如何将这个int值,转变成为color?色即是数
				Color color = new Color(v);

			//设上这个颜色
					g.setColor(color);
				g.fillOval(i/2+40, j/2+70, 2, 2);//改变图片显示的坐标 以及像素点的大小
			}
		}	
	}

	//载入一张图片 将一张图片,转换成二维数组,一个点一个点的在界面上画出
	public int[][] getImage(){
		java.io.File ff = new File("11.jpg");
		//将图片文件载入缓冲图片区
		BufferedImage bi = null;
	try {
		bi = ImageIO.read(ff);//从文件到图片对象
	}catch(Exception ef) {
		ef.printStackTrace();
	}
	int w = bi.getWidth();//图片的宽
	int h = bi.getHeight();//图片的高
	int[][] ia = new int[w][h];//用来装像素点的二维数组
	//取得图片中的像素点
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			//取得内存图片中,指定位置的像素值
			int iv = bi.getRGB(i, j);//i,j位置的color值
			ia[i][j] = iv;//每个像素点的color存入数组
		}
	}
	System.out.println("载入图片成功!");
	return ia;
	}
}

         如上图,在监听器中将图像转换成二维数组即可实现图像的显示;在监听器程序中可以通过改变像素点的大小以及间距(i,j的循环递增值 以及像素点的宽和高),就可以实现图像的模糊处理。 其次,实现图像的二值化,就是利用int创建颜色,将颜色进行拆分后,重新构造一个颜色的填充方式,对图片进行特效处理。

二值化部分代码如下:

    Color color = new Color(v);	
    //二值化	
	//拆分颜色
	int rc = color.getRed();
	int rg = color.getGreen();
	int rb = color.getBlue();
	//重新构造一个颜色
	color = new Color(rc,rg,rb);
    //改变条件,即可改变颜色的填充范围
	if(rc>100) {     
		g.setColor(Color.red);
	}else{
		g.setColor(Color.black);
	}

二值化效果图:给拆分的颜色添加填充条件            如果将Color的(v)变成(-v)。效果图如下:

  灰度图像效果图:取R,G,B三个分量的平均值         单通道图像效果图:仅用R,G,B中某一值     即可:int sum =(rc+rg+rb)/3                                    ,另外两个置0。color = new Color(rg,0,0);                  color = new Color(sum,sum,sum);   

 

除此之外,还可以通过添加条件,改变数据等方法,实现图片的去背景、珠纹化、马赛克、黑白、油画等效果。

1.去背景效果。原理是限制颜色填充的区域,只画高于某一值的颜色,即可实现去背景效果

int[][] ia = getImage();
        for(int i=0;i<ia.length;i+=1) {
            for(int j=0;j<ia[i].length;j+=1) {
                int v= ia[i][j];    //取得一个int代表当前位置的像素值
                Color color = new Color(v);    
                //拆分颜色
                int rc =color.getRed();   int rg = color.getGreen();   int rb = color.getBlue();
                if(rc>120) {      //填充颜色条件
                        g.setColor(color);   //设上这个颜色
                        g.fillOval(i/2+120, j/2+120, 2, 2); //圆形
                }

             }

         }

 

 2.珠纹化效果。原理是增加两个像素点之间的距离,改变i,j的自增值,以及像素点的宽高

    int[][] ia = getImage();
        for(int i=0;i<ia.length;i+=16) {
            for(int j=0;j<ia[i].length;j+=16) {
                int v= ia[i][j];         //取得一个int代表当前位置的像素值
                Color color = new Color(v);    
            //拆分颜色
                int rc =color.getRed();   int rg = color.getGreen();   int rb = color.getBlue();
                    g.setColor(color);      //设上这个颜色
                    g.fillOval(i/2+40, j/2+70, 8, 8); //圆形
            }
        }    

3.马赛克效果。原理添加随机数,设置像素点的大小随机取值,增加间距。

int[][] ia = getImage();
        for(int i=0;i<ia.length;i+=10) {
            for(int j=0;j<ia[i].length;j+=10) {
                int v= ia[i][j];      //取得一个int代表当前位置的像素值
                Color color = new Color(v);    
                           g.setColor(color);         //设上这个颜色
                    //随机数添加马赛克
                    Random rand = new Random();
                    int w = rand.nextInt(20);  
                    g.fillRect(i/2+40, j/2+70, w, w);    //正方形
            }
        }    

4.黑白效果。原理是设置填充条件,大于某个值填充黑色,否则填充白色。

        int rc =color.getRed();    int rg = color.getGreen();    int rb = color.getBlue();
                if(rc>120) {
                      g.setColor(color.BLACK); 
                }else {
                      g.setColor(color.WHITE);
                }
                      g.fillOval(i/2+40, j/2+70, 2, 2); //圆形

5.油画效果。原理 填充随机大小的色块

int[][] ia = getImage();
        for(int i=0;i<ia.length;i+=5) {
            for(int j=0;j<ia[i].length;j+=5) {
                int v= ia[i][j];        //取得一个int代表当前位置的像素值

                Color color = new Color(v);    
                g.setColor(color);
                    //随机数添加马赛克
                    Random rand = new Random();
                    int w = rand.nextInt(20)+5;
                    g.fillOval(i/2+40, j/2+70, w, w); //油画

            }       

        }

色即是数,数即是色!!!  想要改变图片效果,将图片看作是二维数组,改变数据即可得到想要的效果。

三、在第二版本的基础上,添加菜单栏以及菜单的文件选项,可以在在系统文件夹中选择任意一张照片,显示在画布中

Mune(菜单)是窗体程序最常用的一种组件,在Swing体系中,有两种菜单:

        1、基于菜单条的,一般加在JFrame组件上;

        2、JpopupMenu:可以其它swing组件是单击右键的弹出式菜单。

创建窗体对象上的菜单条,菜单条上的菜单由三部分组成:

        javax.swing.Jmenubar类:放置菜单的菜单条,可以通过new Jmenubar()构造菜单条对象;

        javax.swing.JMenu:菜单目录对象,new JMenu("文件"),构造一个菜单条目对象;

        javax.swing.JmenuItem:菜单条目录,new JmenuItem(“菜单条目1”)创建;

        以上三者关系是:JMenu放在JmenuBar上,JmenuItem放在JMenu上。

如何获取电脑中的文件,实现打开按钮,可以直接百度,别人写好的直接拿来用就可以。

具体实现代码如下:

package TuXiang1;

import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class tuxiang3 extends JFrame {
private DrawLis3 dl = null;

public void initUI(){
	this.setSize(600,600);
	this.setTitle("图像处理");
	this.setDefaultCloseOperation(3);
	this.setVisible(true);
	
	FlowLayout fl = new FlowLayout();
	this.setLayout(fl);
	//加上按钮
	JButton buDraw = new JButton("添加图片");
	this.add(buDraw);
	//加菜单栏
	JMenuBar mb = getMB();
	this.setJMenuBar(mb);
	
	//加监听器
	this.setVisible(true);
	//获取画布,一定在界面可见之后
	Graphics g = this.getGraphics();
	this.dl = new DrawLis3(g);
	buDraw.addActionListener(dl);
}

	//创建菜单 返回一个菜单条
	public JMenuBar getMB(){
		JMenuBar mb = new JMenuBar();
	//加菜单
	JMenu jmFile = new JMenu("文件");
	JMenu jmOpp = new JMenu("操作");
	mb.add(jmFile);
	mb.add(jmOpp);
	//给菜单加上菜单项
	JMenuItem miOpen = new JMenuItem("打开");
	//以匿名内部类的形式,加上监听器
	miOpen.addActionListener(new ActionListener() {
		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO 自动生成的方法存根
			System.out.println("Open..........");
			//获取电脑中的文件  看不懂没关系 知道怎么用就可以
			JFileChooser chooser = new JFileChooser();
	        chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
	        chooser.showDialog(new JLabel(), "选择");
	        File file = chooser.getSelectedFile();
	        String fName = file.getAbsoluteFile().toString();
	        
	        dl.setImageFile(fName);
	        System.out.println("已选择文件名是" + fName);
		}
	});
        //创建菜单项
		JMenuItem miNew = new JMenuItem("新建");	
		JMenuItem miSave = new JMenuItem("保存");
		JMenuItem miExit = new JMenuItem("退出");
        //将上述菜单项加到功能菜单上
		jmFile.add(miOpen);
		jmFile.add(miNew);
		jmFile.add(miSave);
		jmFile.add(miExit);
		return mb;		
	}
		public static void main(String[] args) {
		tuxiang3 lu=new tuxiang3();
		lu.initUI();
		}
	}
package TuXiang1;

import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;

public class DrawLis3 implements ActionListener{
	
	private Graphics g;
	private String imageFileName = null;//要打开的图片文件名
	public DrawLis3(Graphics g) {this.g=g;}
	public void setImageFile(String sf) {
		this.imageFileName = sf;
	}
	public void actionPerformed(ActionEvent e) {	
		//改为画上一张图片
		int[][] ia = getImage();
		for(int i=0;i<ia.length;i++) {
			for(int j=0;j<ia[i].length;j++) {
				//取得一个int代表当前位置的像素值
				int v= ia[i][j];
			//如何将这个int值,转变成为color?色即是数
				Color color = new Color(v);
				
			//设上这个颜色
					g.setColor(color);
				g.fillOval(i/2+120, j/2+120, 2, 2);
			}
		}	
	}

	//载入一张图片 将一张图片,转换成二维数组,一个点一个点的在界面上画出
	public int[][] getImage(){
		System.out.println("要打开的图片文件名是" + imageFileName);
		File ff = new File(imageFileName);
		//将图片文件载入缓冲图片区
		BufferedImage bi = null;
	try {
		bi = ImageIO.read(ff);//从文件到图片对象
	}catch(Exception ef) {
		ef.printStackTrace();
	}
	
	int w = bi.getWidth();//图片的宽
	int h = bi.getHeight();//图片的高
	int[][] ia = new int[w][h];//用来装像素点的二维数组
	//取得图片中的像素点
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			//取得内存图片中,指定位置的像素值
			int iv = bi.getRGB(i, j);//i,j位置的color值
			ia[i][j] = iv;//每个像素点的color存入数组
//			System.out.println("getImage 中" +i+" "+j+ "位置像素值是"+iv);
		}
	}
	System.out.println("载入图片成功!");
	return ia;
	
	}
}

 

        如上所示,添加了菜单栏,我们就可以选择电脑中任意一张照片。通过改变数据和颜色,就可以对任意一张照片做效果处理。

四、添加滑杆组件,通过滑动滑杆控制图片的大小

        滑杆组件为javax.swing.JSlider,通常用来调节颜色、数值;监听器需实现ChangeListener,可获取事件源即拖动的JSlider;在监听器中,得到JSllider拖动时的当前值。

先为界面添加滑杆组件:JSlider js = new JSlider();

package TuXiang1;

import java.awt.FlowLayout;
import java.awt.Graphics;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JSlider;

	public class tuxiang5 extends JFrame {		
		public void initUI(){
			this.setSize(600,600);
			this.setTitle("图像处理");
			this.setDefaultCloseOperation(3);
			this.setVisible(true);
			FlowLayout fl = new FlowLayout();
			this.setLayout(fl);

			//加上按钮
			JButton buDraw = new JButton("添加图片");
			this.add(buDraw);
			
			//滑杆
			JSlider js = new JSlider();
			this.add(js);
			//加监听器
			this.setVisible(true);
		
			//获取画布,一定在界面可见之后
			Graphics g = this.getGraphics();
			DrawLis5 dl = new DrawLis5(g,js);
			//加监听器 o.addXXXXListener(接口 k)
			js.addChangeListener(dl);
			buDraw.addActionListener(dl);
		}
public static void main(String args[]) {
		tuxiang5 lu=new tuxiang5();
		lu.initUI();
	}
}

        接下来,需要在监听器类中实现滑块的具体功能。如果要用滑块改变图片的大小,需要创建一块内存缓冲区,将图片画在内存缓冲区中。利用接口implements分别实现按钮和滑杆的方法。

package TuXiang1;

import javax.imageio.ImageIO;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
//1.画图按钮的监听器,点一下画个东西出来
//2.拉杆的监听器

public class DrawLis5 implements ActionListener,ChangeListener{
	
	private Graphics g;
	private JSlider js;//界面上的拉杆
	private int[][] ia;//要初始化的从文件读取的图片数组
	
	public DrawLis5(Graphics g,JSlider js){
		this.g=g;
		this.js=js;
		//装在一张默认的图片
		ia = getImage();
	}

	//当拉杆拉动时,此方法被调用
	public void stateChanged(ChangeEvent e){
		int v = js.getValue();
		System.out.println("js的当前值是"+v);
		
		//记录一下时间
		long start = System.currentTimeMillis();
		System.out.println("开始时时间是" +start);
		//创建一块内存缓冲区,一张内存图片
		BufferedImage buffrer = new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);
			Graphics bufferG = buffrer.getGraphics();//缓冲区图片
		
		for(int i=0;i<ia.length;i+=1) { //100
			for(int j=0;j<ia[i].length;j+=1) { //100
			//取得一个int代表当前位置的像素值
				int iv= ia[i][j];
			//如何将这个int值,转变成为color?色即是数
				Color color = new Color(iv);	
			//设上这个颜色和画图,都画到内存缓冲区中
				bufferG.setColor(color);
				//java→os→cpu→内存→总线→显卡→液晶点
				bufferG.fillOval(i/v, j/v, 2, 2); //圆形
				}
			}
		//将内存图片,画到界面的画布上
		g.drawImage(buffrer,40,70,null);
		
		//记录一下时间
		long end = System.currentTimeMillis();
		long cost = end - start;
		System.out.println("绘制用时:"+(end-start));
		
	}
	//当按下按钮时,此方法被调用
	public void actionPerformed(ActionEvent e) {	
		int v = js.getValue();
		System.out.println("js的当前值是"+v);
		
	
		//记录一下时间
		long start = System.currentTimeMillis();
		System.out.println("开始时时间是" +start);
		//创建一块内存缓冲区,一张内存图片
		BufferedImage buffrer = new BufferedImage(500,500,BufferedImage.TYPE_INT_RGB);
			Graphics bufferG = buffrer.getGraphics();//缓冲区图片
		
		for(int i=0;i<ia.length;i+=1) { //100
			for(int j=0;j<ia[i].length;j+=1) { //100
			//取得一个int代表当前位置的像素值
				int iv= ia[i][j];
			//如何将这个int值,转变成为color?色即是数
				Color color = new Color(iv);	
				bufferG.setColor(color);
				//java→os→cpu→内存→总线→显卡→液晶点
				bufferG.fillOval(i/v, j/v, 2, 2); //圆形
			}
		}
		//将内存图片,画到界面的画布上
		g.drawImage(buffrer,40,70,null);
		
		//记录一下时间
		long end = System.currentTimeMillis();
		long cost = end - start;
		System.out.println("绘制用时:"+(end-start));

		}	

	//载入一张图片 将一张图片,转换成二维数组,一个点一个点的在界面上画出
	public int[][] getImage(){
		java.io.File ff = new File("00.jpg");
		//将图片文件载入缓冲图片区
		BufferedImage bi = null;
	try {
		bi = ImageIO.read(ff);//从文件到图片对象
	}catch(Exception ef) {
		ef.printStackTrace();
	}
	
	int w = bi.getWidth();//图片的宽
	int h = bi.getHeight();//图片的高
	int[][] ia = new int[w][h];//用来装像素点的二维数组
	//取得图片中的像素点
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			//取得内存图片中,指定位置的像素值
			int iv = bi.getRGB(i, j);//i,j位置的color值
			ia[i][j] = iv;//每个像素点的color存入数组
		}
	}
	System.out.println("载入图片成功!");
	return ia;
	
	}

}

 

 滑动滑块时,图片的大小会随之变化,同时控制台也会输出当前图片的大小,绘制所用的时间。

五、两张图片叠加效果。存入两张照片,分别填充颜色,可以调节图片的透明度。

 监听器类代码:

package TuXiang1;

import javax.imageio.ImageIO;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
//画图按钮的监听器,点一下画个东西出来
public class DrawLis6 implements ActionListener{
	
	private Graphics g;
	public DrawLis6(Graphics g) {this.g=g;}
	public void actionPerformed(ActionEvent e) {
		
		//改为画上一张图片  a,b图叠加效果
		int[][] ia = getImage("123.jpg");
		int[][] ib = getImage("456.jpg");
		for(int i=0;i<ia.length;i++) {
			for(int j=0;j<ia[i].length;j++) {
				//取得a图片的颜色值
				int v= ia[i][j];
				Color acolor = new Color(v);
				int arc = acolor.getRed();
				int arg = acolor.getGreen();
				int arb = acolor.getBlue();
				//取得b图片的颜色值
				v=ib[i][j];
				Color bcolor = new Color(v);
				int brc = bcolor.getRed();
				int brg = bcolor.getGreen();
				int brb = bcolor.getBlue();
				
				int lastR = (int)(arc*0.5+brc*0.5);
				int lastG = (int)(arg*0.5+brg*0.5);
				int lastB = (int)(arb*0.5+brb*0.5);
				Color ccc = new Color(lastR,lastG,lastB);
				
			//设上这个颜色
				g.setColor(ccc);
				g.fillOval(i/3+80, j/3+100, 2, 2);
			}
		}	
	}

	//载入一张图片 将一张图片,转换成二维数组,一个点一个点的在界面上画出
	public int[][] getImage(String fname){
		java.io.File ff = new File(fname);
		//将图片文件载入缓冲图片区
		BufferedImage bi = null;
	try {
		bi = ImageIO.read(ff);//从文件到图片对象
	}catch(Exception ef) {
		ef.printStackTrace();
	}
	
	int w = bi.getWidth();//图片的宽
	int h = bi.getHeight();//图片的高
	int[][] ia = new int[w][h];//用来装像素点的二维数组
	//取得图片中的像素点
	for(int i=0;i<w;i++) {
		for(int j=0;j<h;j++) {
			//取得内存图片中,指定位置的像素值
			int iv = bi.getRGB(i, j);//i,j位置的color值
			ia[i][j] = iv;//每个像素点的color存入数组
		}
	}
	System.out.println("载入图片成功!");
	return ia;
	
	}
}

             改变图片的填充饱和度,即可改变透明度

                int lastR = (int)(arc*0.5+brc*0.5);
                int lastG = (int)(arg*0.5+brg*0.5);
                int lastB = (int)(arb*0.5+brb*0.5);
                Color ccc = new Color(lastR,lastG,lastB);

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值