Java实现图片渲染((拖动)马赛克、黑白照、油画风格等)


github源代码下载: 图片渲染源代码.

方法改进

紧接上一篇实现图片渲染链接: 图片渲染(图像编码原理).

可以发现:只前在绘画图片的时候速度非常的慢。那是因为每次只要一获得像素就立即将其绘画出来。

g.setColor(color);
g.fillRect(i, j,1, 1)

在内存中执行代码后,会向GPU请求刷新屏幕,一张图片有成千上万个像素,那么屏幕就会连续刷新很多次,速度非常慢。例如,如果电脑屏幕的刷新率是60赫兹的话,意味着一秒钟屏幕会刷新60次,放到这里来讲的话,一秒钟最多显示60个像素,对于分辨率极高的图片,要加载出来,可想而知等的时间也就会越久。

所以,就要用一种方法一次性将所有的像素画出来。BufferedImage是一个带缓冲区图像类,主要作用是将一幅图片加载到内存中(BufferedImage生成的图片在内存里有一个图像缓冲区,利用这个缓冲区我们可以很方便地操作这个图片)

在请求刷新屏幕之前,现将所有的像素设置完毕,然后一次性将缓冲区的像素全部画出来(刷新一次屏幕)。有两种方法来设置缓冲区。
第一:直接设置缓冲区相应位置像素的RGB值。
实现如下:

//绘画原图改进方法
	public BufferedImage paint1(Graphics g,int[][] arrpixel)
	{	    
		BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);
		for(int i=0;i<arrpixel.length;i++)
		{
			for(int j=0;j<arrpixel[0].length;j++)
			{
				int value=arrpixel[i][j];				 
				buffimage.setRGB(i, j, value);//一次性将所有像素存储完成
			}
		}				
		  g.drawImage(buffimage, 0, 0, null);//一次性画完				  		
		  return buffimage;
		  
	}

第二:通过缓冲区获得画笔,将画笔赋相应的RGB值,然后通过fillRect方法来填充矩形小像素。这种方法还可以方便我们实现渲染(如后面的马赛克等)
实现如下:

//原图改进方法
public BufferedImage paint1(Graphics g,int[][] arrpixel)
	{	    
		BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);
	    Graphics ng=buffimage.getGraphics();
		for(int i=0;i<arrpixel.length;i++)
		{
			for(int j=0;j<arrpixel[0].length;j++)
			{
				int value=arrpixel[i][j];
				 if(i==0&&j==0)
				  { System.out.println("arrpixel:"+value);}
				 ng.setColor(new Color(value));
				 ng.fillRect(i, j, 1, 1);				
			}
		}				
		  g.drawImage(buffimage, 0, 0, null);		  		  
	}

之后就可以把其他的渲染方法逐个改进。以下是图片渲染程序的源代码。

ImageUI

public class ImageUI extends JPanel {
	 String []bt= {"原图","方形马赛克","灰度","二值化","轮廓检测","油画绘制","拖动原图马赛克","拖动彩色马赛克","截图","放大","缩小","撤回上一步","清空图片"};
	 ImageListener listener=new ImageListener();//什么时候static final
	 JFrame nj=new JFrame();//截图确认窗口
	public void initUI()
	{
		JFrame jf=new JFrame();
		jf.setSize(1500,780);
		jf.setTitle("图片处理");
		jf.setDefaultCloseOperation(3);
		jf.setLocationRelativeTo(null);
		
		
		//按钮功能区面板
		JPanel jp1=new JPanel();
		jp1.setBackground(new Color(0xafeeee));
		Dimension dm=new Dimension(200,780);
		jp1.setPreferredSize(dm);
		Dimension btdm=new Dimension(190,40);		
		for(int i=0;i<bt.length;i++)
		{
			JButton jb =new JButton(bt[i]);
			jb.setPreferredSize(btdm);
			jb.setBackground(Color.white);
			Font font= new Font("黑体",Font.BOLD,20);
			jb.setFont(font);
			jb.setForeground(new Color(0x000080));
			jb.setBackground(new Color(0xf0fff0));
			jb.addActionListener(listener);
			jp1.add(jb);
		}
		
	    //绘图区jframe默认边框布局				
		this.setBackground(new Color(0xffffe0));
		jf.add(jp1,BorderLayout.EAST); 
		jf.add(this,BorderLayout.CENTER);

		this.addMouseListener(listener);
		this.addMouseMotionListener(listener);
		this.addKeyListener(listener);
		jf.setVisible(true);

		//从jp2 获得画笔
		Graphics g=jf.getRootPane().getGraphics();
		listener.setgraphics(g);
		listener.setjpanel(this);
					
		nj.setTitle("提示");
		nj.setSize(300, 150);
		//nj.setDefaultCloseOperation(3);
		//这里弹出窗口点叉不能设置关闭程序,否则主界面也会跟着关闭
		nj.setLocationRelativeTo(jf);
		nj.setResizable(false);
		
		JLabel txt =new JLabel("是否确认截图",JLabel.CENTER);
		Font fnt= new Font("黑体",Font.BOLD,30);
		txt.setFont(fnt);
		nj.setLayout(new FlowLayout());
		nj.add(txt);
		
		Font fnt2=new Font("黑体", Font.CENTER_BASELINE, 15);
		JButton bt =new JButton("确认");
		bt.addActionListener(listener);
		bt.setPreferredSize(new Dimension(100, 30));
		bt.setFont(fnt2);
		nj.add(bt);
		
		JButton bt2=new JButton("取消");
		bt2.addActionListener(listener);
		bt2.setPreferredSize(new Dimension(100, 30));
		bt2.setFont(fnt2);
		nj.add(bt2);
	    nj.addWindowListener(listener);
	}
	
	
	@Override
	public void paint(Graphics g) {
		// TODO Auto-generated method stub
		 super.paint(g);		  		
		 		 System.out.println("fresh"+!listener.freshbuff.isEmpty());
		    if( !listener.freshbuff.isEmpty())
		       {
		        BufferedImage top=( BufferedImage)listener.freshbuff.peek();
			     g.drawImage(top,0,0,top.getWidth(),top.getHeight() ,null);		
			     System.out.println("调用paint");
	           }
	}
	
	public void clear(Graphics g)
	{
		super.paint(g);
	}
	
	public static void main(String[] args) {
		new ImageUI().initUI();
		
	}
	
}

ImageListener

#前提说明:
如果一个类需要的接口太多,且接口中的方法又有很
多,且大部分无用,而这个类又不需要继承,那么就可以考虑做一个工具类——实现所有的接口。 然后用所需的类继承这个工具类,选择性的重写方法。
这里监听器类为ImageListener,继承监听器工具类ListenerUtils ,选择性重写接口方法:

  public class ImageListener extends ListenerUtils
{
  //选择性重写
  ... ...
}

public class ListenerUtils implements ActionListener,MouseListener,MouseMotionListener
,KeyListener,ChangeListener,WindowListener{

	@Override
	public void stateChanged(ChangeEvent e) {
		// TODO Auto-generated method stub
		
	}
	... ... ... ... ..

为了更好得实现返回上一步功能,定义了两个BufferedImage栈,考虑到,窗口改变执行的peek()操作,返回上一步执行的是pop()操作,所以用一个栈不容易将功能正确实现。(读者也可以自己定义不同的数据类型存储BufferedImage,可能会更加方便)
刷新栈:
窗口改变大小实现图片重绘。

public Stack<BufferedImage> freshbuff=new Stack<BufferedImage>();

操作栈:
记录每一次的执行结果,以实现返回上一步功能。

public Stack<BufferedImage> buffstack =new Stack<BufferedImage>();

具体代码如下:

public class ImageListener extends ListenerUtils {
	
	int[][] imgarr;
	String btn="";
	String path="E:\\java\\eclipse\\eclipse javaee\\workspace\\Yu java\\66.jpg";
	private Graphics g;
	ImageUtils imageff;
    ImageUI jp;
	public Stack<BufferedImage> buffstack =new Stack<BufferedImage>();
	public Stack<BufferedImage> freshbuff=new Stack<BufferedImage>();
	int index;
    int p_x,p_y;
    int r_x,r_y;
    int d_x,d_y;
    		
	public void setgraphics(Graphics g)
	{
		this.g=g;
	}	
	public void setjpanel(ImageUI jp)
	{
		this.jp=jp;		
	}
	
	//初始化监听器
	ImageListener()
	{		
		imageff=new ImageUtils();
		imgarr=imageff.getImagePixel(path);
		System.out.println("初始化成功"+imgarr.length);
	}
		
	@Override
	public void windowClosing(WindowEvent e) {
		// TODO Auto-generated method stub
		super.windowClosed(e);
     jp.paint(g);         
	}
		
	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		System.out.println("当前"+btn);
		//System.out.println("调用actionperformed");
	    btn=e.getActionCommand();
	    if(btn.equals("原图"))
	    {	
	     jp.clear(g);    		    
	     BufferedImage img=	imageff.paint1(g,imgarr);
	     buffstack.push(img);
	     freshbuff.push(img);
	     System.out.println("栈顶"+buffstack.peek().getWidth());
	     System.out.println("栈内元素数"+buffstack.size());	    
	    }
	    	   	    
	    else if(btn.equals("方形马赛克")) 
	    {  
	    	jp.clear(g); 
	    	imageff.paint2(g, freshbuff,buffstack);		         	    
	    }
	    
	    else if(btn.equals("灰度")) 
	    {	
	    	jp.clear(g);   
	        imageff.paint3(g, freshbuff,buffstack);		    	     
	    }
	    
	    else if(btn.equals("二值化")) 
	    {    
	    	jp.clear(g);
	    	imageff.paint4(g, freshbuff,buffstack);		     	    	 	    	
	    }
	    
	    else if(btn.equals("轮廓检测")) 
	    {   
	    	jp.clear(g);
	    	imageff.paint5(g, freshbuff,buffstack);		    	    	
	    }
	    
	    else if(btn.equals("油画绘制")) 
	    {  
	    	jp.clear(g);
	    	imageff.paint6(g, freshbuff,buffstack);		     		     
	    }
	    
	    else if(btn.equals("放大"))
	    {   
	    	jp.clear(g);
	        imageff.piant7(g, freshbuff,buffstack);	    
	        jp.paint(g);   
	    }
	    
	    else if(btn.equals("缩小"))
	    {  
	    	jp.clear(g);
	    	imageff.paint8(g,freshbuff,buffstack );	    	
	    	jp.paint(g);
	    }
	    
	    else if(btn.equals("清空图片"))
	    {
	      jp.clear(g);
	      imageff.withdraw(g,jp,buffstack,freshbuff);
	    }
	    
	    else if (btn.equals("撤回上一步"))
	    {
	      jp.clear(g);
	      freshbuff.push(imageff.backward(buffstack,g));	   	   
	    }	    
	    
	    else if(btn.equals("确认"))
	    {
	        jp.clear(g);
	    	imageff.paint12(g, freshbuff, buffstack,p_x,p_y,r_x,r_y);
	    	System.out.println("截图完成");
	    	jp.nj.dispose();
	    }
	    
	    else if(btn.equals("取消"))
	    {
	    	jp.nj.dispose();
	    	jp.paint(g);
	    }	    
	}
	
	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		super.mousePressed(e);
		p_x=e.getX();
		p_y=e.getY();
		d_x=e.getX();
		d_y=e.getY();
	}
	
	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		super.mouseReleased(e);
		r_x=e.getX();
		r_y=e.getY();
		if(btn.equals("截图"))
	    {
			Graphics2D g2d=(Graphics2D)g;
			g2d.setStroke(new BasicStroke(2.5f, BasicStroke.CAP_BUTT,
					                      BasicStroke.JOIN_ROUND, 3.5f, new float[] { 10, 5 }, 0f));			
			g2d.setColor(Color.GREEN);
			g2d.drawRect(Math.min(p_x, r_x), Math.min(p_y, r_y),Math.abs(r_x-p_x) ,Math.abs(r_y-p_y));
			jp.nj.setVisible(true);			
	    }
	}
	@Override
	public void mouseDragged(MouseEvent e) {
		// TODO Auto-generated method stub		
		super.mouseDragged(e);	
		int x=e.getX();
		int y=e.getY();
		if(btn.equals("拖动原图马赛克"))
	    {
		   if(Math.abs(x-d_x)>10||Math.abs(y-d_y)>10)		
	           { imageff.paint9(g,freshbuff,buffstack,x,y);		             
	             d_x=x;d_y=y;
	           }	       
	    }
	    		
		if(btn.equals("拖动彩色马赛克")) 
		{
			if(Math.abs(x-d_x)>10||Math.abs(y-d_y)>10)		
	           { imageff.paint10(g,freshbuff,buffstack,x,y);		             
	             d_x=x;d_y=y;
	           }	       	
		}		
	}
	@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		super.keyPressed(e);
	}
}

ImageUtils

图片的渲染代码:
#说明
这里定义一个当前类的布尔全局变量flag,用来判断在返回上一步这个操作中,应该是对操作栈buffstack执行pop()操作还是peek()。例如:因为操作栈中栈顶还存着当前画图结果,如果栈中元素>1的话,得执行两次pop()方法才能返回上一步,这样就得按两次按钮才能实现理想效果。flag等于true表示当前渲染过后的图片还在操作栈中。就得执行两次pop。

public class ImageUtils {	
 boolean flag=true;
 String name=""; 
  
	//读取文件,获得图片像素
	public int[][] getImagePixel(String path) 
	{
		//读取文件的数据
		File file =new File(path);
		//imageIO操作将图片文件的输入输出,
		//读取文件数据
		BufferedImage buffimage=null;
		try {
		   buffimage=ImageIO.read(file);
	       }catch (IOException e) {
		     e.printStackTrace();
		     System.err.println("图像读取失败");
	                              }
	    //获取缓冲图片的大小,初始化保存像素值得二维数组		
		int w=buffimage.getWidth();
		int h=buffimage.getHeight();
	    int [][]arrPixel=new int[w][h];
		for(int i=0;i<w;i++)
		{
			for(int j=0;j<h;j++)
			{
				int pixel=buffimage.getRGB(i, j);
				arrPixel[i][j]=pixel;
			}
		}
		return arrPixel;
	}

   //清空图片	
	public void withdraw(Graphics g,ImageUI jp,Stack<BufferedImage> buff,Stack<BufferedImage> freshbuff)
	{
       jp.clear(g);             
       buff.clear();
       freshbuff.clear();
       flag=true;
	}	
  //原图方法
	public BufferedImage paint1(Graphics g,int[][] arrpixel)
	{	    
		BufferedImage buffimage=new BufferedImage(arrpixel.length, arrpixel[0].length,BufferedImage.TYPE_INT_RGB);
	    Graphics ng=buffimage.getGraphics();
		for(int i=0;i<arrpixel.length;i++)
		{
			for(int j=0;j<arrpixel[0].length;j++)
			{
				int value=arrpixel[i][j];
				 if(i==0&&j==0)
				  { System.out.println("arrpixel:"+value);}
				 ng.setColor(new Color(value));
				 ng.fillRect(i, j, 1, 1);
				//buffimage.setRGB(i, j, value);//一次性将所有像素存储完成
			}
		}				
		  g.drawImage(buffimage, 0, 0, null);
		  flag=true;		
		  return buffimage;		  
	}

	//方形马赛克改进算法
	public void paint2(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
	{	
		if(!freshbuff.isEmpty())
		{
		BufferedImage buff=freshbuff.peek();
		int newwidth=buff.getWidth();
		int newheight=buff.getHeight();
		BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);		
		Graphics ng=buffimage.getGraphics();
		for(int i=0;i<newwidth;i+=10)
		{
		  for(int j=0;j<newheight;j+=10)
		  {   
			    int rgb=buff.getRGB(i, j);			    			   
			    ng.setColor(new Color(rgb));
			    ng.fillRect(i, j, 10, 10);			    
		  }
		}				
		 g.drawImage(buffimage, 0, 0, null);
		 flag=true;	
		 freshbuff.push(buffimage);
		 stackbuff.push(buffimage);
		}	
	}	
     //灰度方法
		public void paint3(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
			{ 			
			if(!freshbuff.isEmpty())
			{
			BufferedImage buff=freshbuff.peek();
			int newwidth=buff.getWidth();
			int newheight=buff.getHeight();
			BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);	
			for(int i=0;i<buff.getWidth();i++)
			{
				for(int j=0;j<buff.getHeight();j++)
				{
					int value =buff.getRGB(i, j);
					int red=(value>>16)&0xFF;
				    int green=(value>>8)&0xFF;
				    int blue=(value>>0)&0xFF;				    				 
				    int gray =(red+green+blue)/3;
				    int newvalue=(gray<<16)+(gray<<8)+(gray<<0);
					buffimage.setRGB(i, j, newvalue);//一次性将所有像素存储完成
				}
			}			  
			  g.drawImage(buffimage, 0, 0, null);			
			    flag=true;
				freshbuff.push(buffimage);
				stackbuff.push(buffimage);			
			}
			  
		}
//二值化方法
public void paint4(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
	
	if(!freshbuff.isEmpty())
	{
	BufferedImage buff=freshbuff.peek();
	int newwidth=buff.getWidth();
	int newheight=buff.getHeight();
	BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);	
	for(int i=0;i<newwidth;i++)
	{
		for(int j=0;j<newheight;j++)
		{
			int value =buff.getRGB(i, j);
			int red=(value>>16)&0xFF;
		    int green=(value>>8)&0xFF;
		    int blue=(value>>0)&0xFF;
		    int gray=(int)(red*0.4+green*0.5+blue*0.6);
		   // int newvalue=(gray<<16)+(gray<<8)+(gray<<0);
		    if(gray<150)
		    {
		    	buffimage.setRGB(i, j, Color.black.getRGB());
		    }
		    else
		    {
		    	buffimage.setRGB(i, j, Color.white.getRGB());
		    }	    			
		}
	}
	
	   g.drawImage(buffimage, 0, 0, null);	
	    flag=true;
		freshbuff.push(buffimage);
		stackbuff.push(buffimage);		
	}
	  
	 
}	
//轮廓检测
//相邻之间的像素点进行比较
public void paint5(Graphics g ,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{	
	if(!freshbuff.isEmpty())
	{
	BufferedImage buff=freshbuff.peek();
	int newwidth=buff.getWidth();
	int newheight=buff.getHeight();
	BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);	
	for(int i=0;i<newwidth-2;i++)
	{
		for(int j=0;j<newheight-2;j++)
		{
			int value =buff.getRGB(i, j);
			int red=(value>>16)&0xFF;
		    int green=(value>>8)&0xFF;
		    int blue=(value>>0)&0xFF;
		    
		    int valuen=buff.getRGB(i+2, j+2);
		    int redn=(valuen>>16)&0xFF;
		    int greenn=(valuen>>8)&0xFF;
		    int bluen=(valuen>>0)&0xFF;
          //int gray =(red+green+blue)/3;
          int gray =(int)(red*0.41+green*0.28+blue*0.31);
          int grayn =(int)(redn*0.41+greenn*0.28+bluen*0.31);
          
          if(Math.abs(gray-grayn)>15){
              buffimage.setRGB(i, j, Color.pink.getRGB());
          }else{
        	  buffimage.setRGB(i, j, Color.white.getRGB());
          }   		    
		}
	}	
	g.drawImage(buffimage, 0, 0, null);
	flag=true;
	freshbuff.push(buffimage);
	stackbuff.push(buffimage);		
	}	
}
//油画算法
public void paint6(Graphics g ,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{	
	if(!freshbuff.isEmpty())
	{
	BufferedImage buff=freshbuff.peek();
	int newwidth=buff.getWidth();
	int newheight=buff.getHeight();
	BufferedImage buffimage=new BufferedImage(newwidth,newheight,BufferedImage.TYPE_INT_RGB);	
	Random random = new Random();
	int size=random.nextInt(5); 
	for(int i=0;i<newwidth;i+=3)
	{
	  for(int j=0;j<newheight;j+=3)
	  {   
		    int pixel=buff.getRGB(i, j);
		    int h=i,m=j;
		    for(int k=0;k<3;k++)
		    {  			    
		      for(int p=0;p<3;p++)
		       {		    	   
		    	  if(h<newwidth&&m<newheight)
		    	  buffimage.setRGB(h,m++,pixel);			    	
		       }
		        h++;
		        m=j+size;
		    }		   
	  }
	}	
	g.drawImage(buffimage, 0, 0, null);
	flag=true;
	freshbuff.push(buffimage);
	stackbuff.push(buffimage);		
	}
}
//截图
public void paint12(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int px,int py,int rx,int ry)
{
	if(!freshbuff.isEmpty())
	{
		BufferedImage buff=freshbuff.peek();
		int newwidth=Math.abs(px-rx);
		int newheight=Math.abs(py-ry);		
		
		BufferedImage  buffimage=new BufferedImage(newwidth, newheight, BufferedImage.TYPE_INT_RGB);
		int minx=Math.min(rx, px);
		int maxx=Math.max(rx, px);
		int miny=Math.min(ry, py);
		int maxy=Math.max(ry, py);
		System.out.println("minx"+minx+"maxx"+maxx+"miny"+miny+"maxy"+maxy);
		int h=0,m=0;
		for(int i=minx;i<=maxx;i++)
		{
			for(int j=miny;j<=maxy;j++)
			{
				int rgb=buff.getRGB(i, j);					
				if(h<newwidth&&m<newheight)
			        {
					buffimage.setRGB(h, m++, rgb);
			        }							        
			}
			h++;
			m=0;
		}				
     	g.drawImage(buffimage, 0, 0, null);		
		flag=true;
		freshbuff.push(buffimage);
		stackbuff.push(buffimage);		
	}
}
//放大
public void piant7(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
	if(!freshbuff.isEmpty())
	{
	BufferedImage buff=freshbuff.peek();
	int newwidth=buff.getWidth()+(int)((buff.getWidth()*20)/100);
	int newheight=buff.getHeight()+(int)((buff.getHeight()*20)/100);
	
	BufferedImage buffimage=new BufferedImage(newwidth, newheight, BufferedImage.TYPE_INT_RGB);	
	Graphics ng=buffimage.getGraphics();
	ng.drawImage(buff,0,0, newwidth, newheight, null);
		
	g.drawImage(buffimage,0,0, null);
	flag=true;
	freshbuff.push(buffimage);
	stackbuff.push(buffimage);	
	}	
}
//缩小
public void paint8(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff)
{
	if(!freshbuff.isEmpty())
	{
	BufferedImage buff=freshbuff.peek();	
	int newwidth=(int)((buff.getWidth()*80)/100);
	int newheight=(int)((buff.getHeight()*80)/100);
	
	BufferedImage buffimage=new BufferedImage(newwidth, newheight,BufferedImage.TYPE_INT_RGB );
	Graphics ng=buffimage.getGraphics();
	ng.drawImage(buff, 0,0,newwidth, newheight, null);//一定要注明起点0,0  
	g.drawImage(buffimage,0,0, null);
	
	flag=true;
	freshbuff.push(buffimage);
	stackbuff.push(buffimage);
	}	
}

//拖动马赛克
public void paint9(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int x,int y)
{    
	if(!stackbuff.isEmpty()) 
	{
	BufferedImage buff= stackbuff.peek();
	BufferedImage buffimage=new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.TYPE_INT_RGB);	
	if(buff.getWidth()<x||buff.getHeight()<y)
		return;
	int rgb=buff.getRGB(x, y);		
	for(int i=0;i<buff.getWidth();i++)
	{
	  for(int j=0;j<buff.getHeight();j++)
	  {   
		    int RGB=buff.getRGB(i, j);		    		
		   buffimage.setRGB(i,j , RGB);			    		    			  			  		   
	  }
	}
	for(int i=x;i<x+20;i++)
	{
		for(int j=y;j<y+20;j++)
		{
			if(i<buffimage.getWidth()&&j<buffimage.getHeight())
			buffimage.setRGB(i, j, rgb);
		}
	}
	g.drawImage(buffimage, 0, 0,buffimage.getWidth(),buffimage.getHeight(), null);
	
	freshbuff.push(buffimage);
	stackbuff.push(buffimage);
	System.out.println("stack"+stackbuff.size());
	flag=true;	
	}
	
}
//拖动彩色马赛克
public void paint10(Graphics g,Stack<BufferedImage> freshbuff,Stack<BufferedImage> stackbuff,int x,int y)
{    
	if(!stackbuff.isEmpty()) 
	{
	BufferedImage buff= stackbuff.peek();
	if(buff.getWidth()<x||buff.getHeight()<y)
	return;
	BufferedImage buffimage=new BufferedImage(buff.getWidth(), buff.getHeight(), BufferedImage.TYPE_INT_RGB);
	
	for(int i=0;i<buff.getWidth();i++)
	{
	  for(int j=0;j<buff.getHeight();j++)
	  {   
		    int RGB=buff.getRGB(i, j);		    		
		   buffimage.setRGB(i,j , RGB);			    		    			  			  		   
	  }
	}
	
	Random ram=new Random();
int rgb=ram.nextInt(0xffffff);

	Graphics ng=buffimage.getGraphics();
	ng.setColor(new Color(rgb));
	ng.fillOval(x, y, 20, 20);
	g.drawImage(buffimage, 0, 0,buffimage.getWidth(),buffimage.getHeight(), null);
	
	freshbuff.push(buffimage);
	stackbuff.push(buffimage);
	System.out.println("stack"+stackbuff.size());
	flag=true;	
	}	
}

//返回上一步
public BufferedImage backward(Stack<BufferedImage> buff,Graphics g)
 {  
	 BufferedImage top=null;
	if(!buff.isEmpty())
		System.out.println("stack"+buff.size());
	{	  
		   if(buff.size()==1)
			  {
			    top=buff.peek();
			  	g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);				 
			  }
		   else
		    {
			  if(flag==true&&buff.size()>1)
	             {
				  top=buff.pop();
			         if(buff.size()==1)
			            {			      
			            top=buff.peek();
			            g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);			           			        		           
			            }  
			         else 
			        	 {
			        	 top=buff.pop();
			        	 g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);		
			        	 }
	             }
			   if(flag==false&&buff.size()>1)
			   {
				  top=buff.pop();
				  g.drawImage(top,0,0,top.getWidth(),top.getHeight(),null);					 
			   }
	         }
		    
	  }  
		       flag=false;	       
	         System.out.println("stack"+buff.size());	        
	         return top;	     
    }
}

演示动画

图片处理 2021-07-21 23-18-15

由于录屏问题,弹出界面没显示,截屏如下

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

GuochaoHN

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

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

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

打赏作者

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

抵扣说明:

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

余额充值