用java的swing写了个图片标注工具

时间:2023-01-28 12:30:03

用java的swing写了个图片标注工具

功能说明:

1 鼠标单击:选取裁剪区域

2 鼠标双击:选取裁剪区域,并把裁剪区域保存为文件,同时把区域中心点的坐标保存

3 打开图片:从某个文件夹打开图片并显示,同时把该目录的所有图片的路径载进来。这个功能主要是针对这么种情况,

假如处理某个文件夹的图片集,在某一张终止了或者暂停了,下一次要从这种图片开始。

4 保存坐标:把裁剪区域保存为文件,同时把区域中心点的坐标保存

5 打开目录:把该目录的所有图片的路径载进来。

6 下一张:展示下一张图片。


常见用法:

1 “打开目录”,这时会将目录图片载进来,并显示第一张,这是可以 “鼠标双击”,选取该张图片的裁剪区域,保存坐标和裁剪区域,并展示下一张。

2 假如用法1在某一张图片暂停了,比如关闭该程序。下次可以利用“打开图片”从某张图片开始,然后继续利用“鼠标双击”一张一张处理。


注:其实按钮“保存坐标”和“下一张”只是作为功能测试使用,实际操作可以用“鼠标双击”代替。


下面附上源代码:


import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.CropImageFilter;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collections;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.filechooser.FileNameExtensionFilter;



public class PhotoFrame extends JFrame 
{

	private static final long serialVersionUID = -2216276219179107707L;
	private Container con;

	private MousePanel zPanel;
	private JScrollPane imgSp;
	private JPanel btnPanel;
	private String imageDir;
	private String currImg;//文件名,不包含目录
	private int currIndex;//当前图片索引
	ArrayList<String> imgList;//所有图片的绝对路径
	
	public void  writeCropImg() throws IOException
	{
		
		BufferedImage sourceImage = (BufferedImage) zPanel.getImg();   

        Image croppedImage; 
        ImageFilter cropFilter; 
        
		int x = zPanel.getPointX()-25;
		int y = zPanel.getPointY()-25;
        //四个参数分别为图像起点坐标和宽高,即CropImageFilter(int x,int y,int width,int height),详细情况请参考API 
        //指定要裁剪的的文件的宽度和高度,以及起始坐标 
        cropFilter =new CropImageFilter(x,y,50,50); 
        //生成图片 
        croppedImage= Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(sourceImage.getSource(),cropFilter)); 
         
        //获取创建后的图片的高度 
        int h1=croppedImage.getHeight(null); 
        int w1=croppedImage.getWidth(null); 
         
        BufferedImage bi=new BufferedImage(w1,h1,BufferedImage.TYPE_INT_RGB); 
         
        Graphics g=bi.getGraphics(); 
        //在画图的时候可以设置背景色 
        g.drawImage(croppedImage,0,0,Color.white,null);

        String dir = imageDir+"_crops";
        
        //创建文件输出流  
        FileOutputStream fos=new FileOutputStream(new File(dir+"/"+currImg)); 
        //将创建的图片写入到输出流 
        ImageIO.write(bi, "png", fos); 
        fos.close(); 
	}
	private void showNext()
	{
		updateCurrName();
		zPanel.setImagePath(imgList.get(currIndex));	
		currIndex++;
		
	}
	private void updateCurrName()
	{
		String path = imgList.get(currIndex);
		int index = path.lastIndexOf('/');
		currImg = path.substring(index);
		
	}
	
	private class nextHandler implements ActionListener
	{
		@Override
		public void actionPerformed(ActionEvent e)
		{
			showNext();			
		}		
	}
	private class openDirHandler implements ActionListener
	{

		@Override
		public void actionPerformed(ActionEvent e) 
		{
			JFileChooser chooser = new JFileChooser();
			chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);//设置只能选择目录
			int returnVal = chooser.showOpenDialog(null);
			if(returnVal == JFileChooser.APPROVE_OPTION) 
			{
			  imageDir =chooser.getSelectedFile().getPath();
			  imgList = FileTool.refreshFileList(imageDir);
			  currIndex = 0;
			  showNext();
			  //System.out.println ( "你选择的目录是:" + selectPath );
			  //你选择的目录是:/home/linger/imdata/collar
			}
			
		}
		
	}
	
	private void savePointAndImg()
	{
		try 
		{
			String dir = imageDir+"_points";
			int x = zPanel.getPointX();
			int y = zPanel.getPointY();
			
			//打开文件
			File f=new File(dir+"/");
			if(!f.exists())
			{					  
				f.mkdir();
				
			}		  
			f=new File(dir+"/"+currImg);
			if(!f.exists())
			{					  
				f.createNewFile();				
			}		  
			FileOutputStream fos=new FileOutputStream(f);
			OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8");
			BufferedWriter bw=new BufferedWriter(osw);			
			//写入文件
			bw.write(x+","+y);
			
			//关闭文件
			bw.close();
			osw.close();
			fos.close();
						
			writeCropImg();
		
		}
		catch (IOException e1) 
		{
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
	}
	private class savePointHandler implements ActionListener
	{

		@Override
		public void actionPerformed(ActionEvent e) 
		{
			 savePointAndImg();			
		}				
	}
	
	private class openImageHandler implements ActionListener 
    { 
        public void actionPerformed(ActionEvent e) 
        { 
        	JFileChooser chooser = new JFileChooser();
        	FileNameExtensionFilter filter = new FileNameExtensionFilter("JPG & PNG Images", "jpg", "png");
        	chooser.setFileFilter(filter);
        	int returnVal = chooser.showOpenDialog(null);
        	if(returnVal == JFileChooser.APPROVE_OPTION) 
        	{
        		  File file = chooser.getSelectedFile();
        		  imageDir = file.getParent();
        		  imgList = FileTool.refreshFileList(imageDir);
        		  currImg = file.getName();//文件名,不包含路径
        		 // System.out.println();
        	      String path = file.getAbsolutePath();
        	      currIndex = imgList.indexOf(path);
        	      zPanel.setImagePath(path);
        	      currIndex++;
        	      //内部类访问外部类,可以直接访问的啊

        	}
        } 
    } 
	
	private PhotoFrame() 
	{
		con = getContentPane();
		con.setLayout(new GridLayout(2,2));
		
		zPanel = new MousePanel();
		//zPanel.setImagePath("/home/linger/17820d01");//绑定图片
		//zPanel.setPreferredSize(new Dimension(zPanel.getImgWidth(), zPanel.getImgHeight()));
		
		imgSp = new JScrollPane();
		imgSp.setPreferredSize(new Dimension(zPanel.getImgWidth(), zPanel.getImgHeight()));
		imgSp.setViewportView(zPanel);
		imgSp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		imgSp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);

		//con.add(imgSp, BorderLayout.CENTER);
		con.add(imgSp);
		
		
		btnPanel  = new JPanel();
		btnPanel.setLayout(new FlowLayout());
		btnPanel.setSize(300,100);
		
		JButton button = new JButton("打开图片");
		button.setSize(100, 50);		
		btnPanel.add(button);
		button.addActionListener(new openImageHandler());		
		
		button = new JButton("保存坐标");
		button.setSize(100, 50);		
		btnPanel.add(button);
		button.addActionListener(new savePointHandler());
		
		button = new JButton("打开目录");
		button.setSize(100, 50);		
		btnPanel.add(button);
		button.addActionListener(new openDirHandler());
		
		button = new JButton("下一张");
		button.setSize(100, 50);		
		btnPanel.add(button);
		button.addActionListener(new nextHandler());
		
		con.add(btnPanel);
		
		
		zPanel.addMouseListener(new MouseAdapter(){
			public void mouseClicked(MouseEvent e)
			{ 
				if(e.getClickCount() == 2)
				{ 
					savePointAndImg();
					showNext();
				} 				
			} 
		});

		
		
		
		finalSetting();
	}

	private void finalSetting() 
	{
		setTitle("标注工具");

		Toolkit kit = Toolkit.getDefaultToolkit();
		Dimension screenSize = kit.getScreenSize();
		int screenHeight = screenSize.height;
		int screenWidth = screenSize.width;
		int frameH = getHeight();
		int frameW = getWidth();
		setLocation((screenWidth - frameW) / 2 - 250,
				(screenHeight - frameH) / 2 - 250);
		
		setSize(800, 600);
		//setSize(zPanel.getImgWidth()+10, zPanel.getImgHeight()+10);
		//setPreferredSize(new Dimension(zPanel.getImgWidth()+100, zPanel.getImgHeight()+100)); 
		//pack();  
		
		setVisible(true);
		setResizable(true);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	public static void main(String[] args) 
	{
		new PhotoFrame();
	}

}




import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.ImageFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

import javax.imageio.ImageIO;

public class ImgPanel extends javax.swing.JPanel 
{

	private static final long serialVersionUID = 1L;
	private Image image;
	private int imgWidth;
	private int imgHeight;

	
	public Image getImg()
	{
		return image;
	}
	
	
	public int getImgWidth() 
	{
		return imgWidth;
	}

	public void setImgWidth(int imgWidth) 
	{
		this.imgWidth = imgWidth;
	}

	public int getImgHeight() 
	{
		return imgHeight;
	}

	public void setImgHeight(int imgHeight) 
	{
		this.imgHeight = imgHeight;
	}

	public ImgPanel() 
	{
	}

	public void setImagePath(String imgPath) {
		// 该方法不推荐使用,该方法是懒加载,图像并不加载到内存,当拿图像的宽和高时会返回-1;
		// image = Toolkit.getDefaultToolkit().getImage(imgPath);
		try 
		{
			// 该方法会将图像加载到内存,从而拿到图像的详细信息。
			image = ImageIO.read(new FileInputStream(imgPath));
			//读取图片的大小
			setImgWidth(image.getWidth(this));
			setImgHeight(image.getHeight(this));
			this.repaint();
		} 
		catch (FileNotFoundException e) 
		{
			e.printStackTrace();
		} catch (IOException e) 
		{
			e.printStackTrace();
		}

	}

	@Override
	public void paintComponent(Graphics g1) 
	{
		super.paintComponent(g1);
		int x = 0;
		int y = 0;
		Graphics g = (Graphics) g1;
		if (null == image) 
		{
			return;
		}

		g.drawImage(image, x, y, image.getWidth(this), image.getHeight(this),
				this);			
		g = null;
	
		
	}
}



import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
public class MousePanel extends ImgPanel//JPanel
{
	int x_pos,y_pos;
	public int getPointX()
	{
		return x_pos;
	}
	public int getPointY()
	{
		return y_pos;
	}
	public MousePanel()
	{
		addMouseListener(new MouseListener()
		{
			//mouseClicked():鼠标单击
			public void mouseClicked(MouseEvent e)
			{
				x_pos=e.getX();
				y_pos=e.getY();
				repaint();
			}
			//mouseEntered():鼠标进入时
			public void mouseEntered(MouseEvent e)
			{
			}
			//mouseExited():鼠标离开时
			public void mouseExited(MouseEvent e)
			{
			}
			//mousePressed():鼠标按下去
			public void mousePressed(MouseEvent e)
			{

			}
			//mouseReleased():鼠标松开时
			public void mouseReleased(MouseEvent e) {}
		});
		addMouseMotionListener(new MouseMotionListener()
		{
			public void mouseMoved(MouseEvent e)
			{
			}
			public void mouseDragged(MouseEvent e){}
		});
	}
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		//g.drawString("current location is:["+x_pos+","+y_pos+"]",x_pos,y_pos);//在界面上显示
		//System.out.printf("current location is:["+x_pos+","+y_pos+"]\n",x_pos,y_pos);//在控制台显示		
        g.setColor(Color.RED);
        g.drawRect(x_pos-25, y_pos-25, 50, 50);
        //g.fillOval(x_pos,y_pos,8,8);

		
	}
}


import java.io.File;
import java.util.ArrayList;


public class FileTool {
	public static ArrayList<String> refreshFileList(String strPath) 
	{ 
		ArrayList<String> filelist = new ArrayList<String>(); 
        File dir = new File(strPath); 
        File[] files = dir.listFiles(); 
        if (files == null) 
        {
            return filelist; 
        }
        for (int i = 0; i < files.length; i++) 
        { 
            if (files[i].isDirectory()) 
            { 
                refreshFileList(files[i].getAbsolutePath()); 
            } 
            else
            { 
                String strFileName = files[i].getAbsolutePath().toLowerCase(); 
                //System.out.println(strFileName); 
                filelist.add(files[i].getAbsolutePath());                    
            } 
        }
        return filelist;
	}
	
	public static void main(String[] args) 
	{
		// TODO Auto-generated method stub
		ArrayList<String>  test = refreshFileList("/home/linger/imdata/collar");
		System.out.println(test.get(668));
		System.out.println(test.get(669));
		System.out.println(test.get(670));
	}

}