Java图片截图缩放工具

最近在做一个图像的软件,为了让用户体验更加舒畅,需要对图像进行截取,对于高分辨率的图像,有缩放功能是最好的了。可惜本人技术水平不高,只能去网上到处找源码啊。倒是给我找到了一个图像截取的,嘛,时间太久了,忘了从哪里找到的了,但是可惜它没有图像缩放的功能,就自己摸索着加上去了,写的比较挫,但是使用起来还算可以了。





import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class ImageCutAndZoomFrame extends JFrame {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static void main(String[] args) {
		new ImageCutAndZoomFrame("test.jpg", System.getProperty("user.dir"));
	}

	public ImageCutAndZoomFrame(String imagePath, String targetPath) {
		super("图像缩放截取窗口 by 皮皮king1");
		BufferedImage bi = null;
		try {
			bi = ImageIO.read(new File(imagePath));
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null, "IOException:未能获取图片", "错误",
					JOptionPane.ERROR_MESSAGE);
			System.exit(0);
		}
		ImageSnapPanel imageSnapPanel = new ImageSnapPanel(bi, targetPath);
		this.add(imageSnapPanel);

		// 设置显示大小
		Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
		int width = (int) (screenDimension.getWidth() * 0.7 > bi.getWidth() ? bi
				.getWidth() : screenDimension.getWidth() * 0.7);
		int height = (int) (screenDimension.getHeight() * 0.7 > bi.getHeight() ? bi
				.getHeight() : screenDimension.getHeight() * 0.7);
		double rate = (double) bi.getHeight() / (double) bi.getWidth();
		if (screenDimension.getHeight() < screenDimension.getWidth())
			width = (int) ((double) height / rate);
		else
			height = (int) ((double) width * rate);
		this.setSize(width, height);
		this.setLocation(
				(int) ((screenDimension.getWidth() - this.getWidth()) / 2),
				(int) ((screenDimension.getHeight() - this.getHeight()) / 2));

		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

}

/**
 * 真正用于图像裁剪的类
 * 
 */
class ImageSnapPanel extends JPanel implements MouseListener,
		MouseMotionListener, MouseWheelListener {

	/**
		 * 
		 */
	private static final long serialVersionUID = 1L;
	private BufferedImage srcBi;
	private BufferedImage bi;
	private int startX, startY, endX, endY, tempX, tempY;
	private Rectangle select = new Rectangle(0, 0, 0, 0);// 表示选中的区域
	private Cursor cs = new Cursor(Cursor.CROSSHAIR_CURSOR);// 表示一般情况下的鼠标状态(十字线)
	private States current = States.DEFAULT;// 表示当前的编辑状态
	private Rectangle[] rec;// 表示八个编辑点的区域
	// 下面四个常量,分别表示谁是被选中的那条线上的端点
	public static final int START_X = 1;
	public static final int START_Y = 2;
	public static final int END_X = 3;
	public static final int END_Y = 4;
	private int currentX, currentY;// 当前被选中的X和Y,只有这两个需要改变
	private Point p = new Point();// 当前鼠标移的地点
	private boolean showTip = true;// 是否显示提示.如果鼠标左键一按,则提示就不再显示了
	private BufferedImage get;
	// private ImageSnapDialog imageSnapDialog;
	private String targetPath;

	private int times;// 放大或缩小倍数
	int xL = 0;// 坐标点左侧距离
	int xR = 0;// 坐标点右侧距离
	int yB = 0;// 坐标点下方距离
	int yA = 0;// 坐标点上方距离
	int x, y, w, h;

	/**
	 * 构造函数
	 * 
	 * @param bi
	 *            传入的图片BufferedImage
	 * @param targetPath
	 *            截图存储目录
	 */
	public ImageSnapPanel(BufferedImage bi, String targetPath) {
		// this.imageSnapDialog = (ImageSnapDialog) imageSnapDialog;

		this.srcBi = bi;
		this.bi = bi;
		this.targetPath = targetPath;
		this.addMouseListener(this);
		this.addMouseMotionListener(this);
		this.addMouseWheelListener(this);
		initRecs();
	}

	private void initRecs() {
		rec = new Rectangle[8];
		for (int i = 0; i < rec.length; i++) {
			rec[i] = new Rectangle();
		}
	}

	public void paintComponent(Graphics g) {
		g.drawImage(bi, 0, 0, this.getWidth(), this.getHeight(), this);
		g.setColor(Color.RED);
		g.drawLine(startX, startY, endX, startY);
		g.drawLine(startX, endY, endX, endY);
		g.drawLine(startX, startY, startX, endY);
		g.drawLine(endX, startY, endX, endY);
		int x = startX < endX ? startX : endX;
		int y = startY < endY ? startY : endY;
		select = new Rectangle(x, y, Math.abs(endX - startX), Math.abs(endY
				- startY));
		int x1 = (startX + endX) / 2;
		int y1 = (startY + endY) / 2;
		g.fillRect(x1 - 2, startY - 2, 5, 5);
		g.fillRect(x1 - 2, endY - 2, 5, 5);
		g.fillRect(startX - 2, y1 - 2, 5, 5);
		g.fillRect(endX - 2, y1 - 2, 5, 5);
		g.fillRect(startX - 2, startY - 2, 5, 5);
		g.fillRect(startX - 2, endY - 2, 5, 5);
		g.fillRect(endX - 2, startY - 2, 5, 5);
		g.fillRect(endX - 2, endY - 2, 5, 5);
		rec[0] = new Rectangle(x - 5, y - 5, 10, 10);
		rec[1] = new Rectangle(x1 - 5, y - 5, 10, 10);
		rec[2] = new Rectangle((startX > endX ? startX : endX) - 5, y - 5, 10,
				10);
		rec[3] = new Rectangle((startX > endX ? startX : endX) - 5, y1 - 5, 10,
				10);
		rec[4] = new Rectangle((startX > endX ? startX : endX) - 5,
				(startY > endY ? startY : endY) - 5, 10, 10);
		rec[5] = new Rectangle(x1 - 5, (startY > endY ? startY : endY) - 5, 10,
				10);
		rec[6] = new Rectangle(x - 5, (startY > endY ? startY : endY) - 5, 10,
				10);
		rec[7] = new Rectangle(x - 5, y1 - 5, 10, 10);
		if (showTip) {
			g.setColor(Color.CYAN);
			g.fillRect(p.x, p.y, 350, 20);
			g.setColor(Color.RED);
			g.drawRect(p.x, p.y, 350, 20);
			g.setColor(Color.BLACK);
			g.drawString("左键选择,右键取消,双击截图,滚轮缩放", p.x, p.y + 15);
		}
	}

	// 根据东南西北等八个方向决定选中的要修改的X和Y的座标
	private void initSelect(States state) {
		switch (state) {
		case DEFAULT:
			currentX = 0;
			currentY = 0;
			break;
		case EAST:
			currentX = (endX > startX ? END_X : START_X);
			currentY = 0;
			break;
		case WEST:
			currentX = (endX > startX ? START_X : END_X);
			currentY = 0;
			break;
		case NORTH:
			currentX = 0;
			currentY = (startY > endY ? END_Y : START_Y);
			break;
		case SOUTH:
			currentX = 0;
			currentY = (startY > endY ? START_Y : END_Y);
			break;
		case NORTH_EAST:
			currentY = (startY > endY ? END_Y : START_Y);
			currentX = (endX > startX ? END_X : START_X);
			break;
		case NORTH_WEST:
			currentY = (startY > endY ? END_Y : START_Y);
			currentX = (endX > startX ? START_X : END_X);
			break;
		case SOUTH_EAST:
			currentY = (startY > endY ? START_Y : END_Y);
			currentX = (endX > startX ? END_X : START_X);
			break;
		case SOUTH_WEST:
			currentY = (startY > endY ? START_Y : END_Y);
			currentX = (endX > startX ? START_X : END_X);
			break;
		default:
			currentX = 0;
			currentY = 0;
			break;
		}
	}

	public void mouseMoved(MouseEvent me) {
		doMouseMoved(me);
		initSelect(current); // current:当前状态(state)
		if (showTip) {
			p = me.getPoint();
			repaint();
		}
	}

	// 特意定义一个方法处理鼠标移动,是为了每次都能初始化一下所要选择的区域
	private void doMouseMoved(MouseEvent me) {
		if (select.contains(me.getPoint())) {
			this.setCursor(new Cursor(Cursor.MOVE_CURSOR));
			current = States.MOVE;
		} else {
			States[] st = States.values();
			for (int i = 0; i < rec.length; i++) {
				if (rec[i].contains(me.getPoint())) {
					current = st[i];
					this.setCursor(st[i].getCursor());
					return;
				}
			}
			this.setCursor(cs);
			current = States.DEFAULT;
		}
	}

	public void mouseExited(MouseEvent me) {
	}

	public void mouseEntered(MouseEvent me) {
	}

	public void mouseDragged(MouseEvent me) {
		int x = me.getX();
		int y = me.getY();
		// 分别处理一系列的(光标)状态(枚举值)
		if (current == States.MOVE) {
			startX += (x - tempX);
			startY += (y - tempY);
			endX += (x - tempX);
			endY += (y - tempY);
			tempX = x;
			tempY = y;
		} else if (current == States.EAST || current == States.WEST) {
			if (currentX == START_X) {
				startX += (x - tempX);
				tempX = x;
			} else {
				endX += (x - tempX);
				tempX = x;
			}
		} else if (current == States.NORTH || current == States.SOUTH) {
			if (currentY == START_Y) {
				startY += (y - tempY);
				tempY = y;
			} else {
				endY += (y - tempY);
				tempY = y;
			}
		} else if (current == States.NORTH_EAST || current == States.NORTH_WEST
				|| current == States.SOUTH_EAST || current == States.SOUTH_WEST) {
			if (currentY == START_Y) {
				startY += (y - tempY);
				tempY = y;
			} else {
				endY += (y - tempY);
				tempY = y;
			}
			if (currentX == START_X) {
				startX += (x - tempX);
				tempX = x;
			} else {
				endX += (x - tempX);
				tempX = x;
			}
		} else {
			startX = tempX;
			startY = tempY;
			endX = me.getX();
			endY = me.getY();
		}
		this.repaint();
	}

	public void mousePressed(MouseEvent me) {
		showTip = false;
		tempX = me.getX();
		tempY = me.getY();
	}

	public void mouseReleased(MouseEvent me) {
		if (me.isPopupTrigger()) { // 右键
			showTip = true;
			p = me.getPoint();
			startX = 0;
			startY = 0;
			endX = 0;
			endY = 0;
			repaint();
		}
	}

	public void mouseClicked(MouseEvent me) {
		int x = (int) ((double) me.getX() / (double) this.getWidth() * (double) srcBi
				.getWidth());
		int y = (int) ((double) me.getY() / (double) this.getHeight() * (double) srcBi
				.getHeight());
		System.out.println("鼠标点击坐标:" + me.getX() + "," + me.getY()
				+ " 在源图中的实际坐标为:" + x + "," + y + " 窗口大小为:" + this.getWidth()
				+ "," + this.getHeight());
		System.out.println();
		if (me.getClickCount() == 2) {
			// Rectangle rec=new
			// Rectangle(startX,startY,Math.abs(endX-startX),Math.abs(endY-startY));
			Point p = me.getPoint();
			if (select.contains(p)) {

				int startx = (int) ((double) select.x
						/ (double) this.getWidth() * (double) bi.getWidth());
				int starty = (int) ((double) select.y
						/ (double) this.getHeight() * (double) bi.getHeight());

				int width = (int) ((double) select.width
						/ (double) this.getWidth() * (double) bi.getWidth());
				int height = (int) ((double) select.height
						/ (double) this.getHeight() * (double) bi.getHeight());
				if (startx < 0) {
					width += startx;
					startx = 0;

				} else if (startx > bi.getWidth())
					startx = bi.getWidth();
				if (starty < 0) {
					height += starty;
					starty = 0;
				} else if (starty > bi.getHeight())
					starty = bi.getHeight();

				if (select.x + select.width > this.getWidth()
						|| select.y + select.height > this.getHeight()) {
					if (select.x + select.width >= this.getWidth()) {
						width = bi.getWidth() - startx;
					}
					if (select.y + select.height >= this.getHeight()) {
						height = bi.getHeight() - starty;
					}
				}

				System.out.println(startx + " " + starty + " " + width + " "
						+ height);
				get = bi.getSubimage(startx, starty, width, height);

				System.out.println("截图区域为:从(" + startx + "," + starty
						+ ") 开始长宽为(" + width + "," + height + ") 的区域");

				// 以时间为名称,保存到文件
				String format = "jpg";
				File file = new File(
						targetPath
								+ File.separator
								+ new SimpleDateFormat("yyyyMMddHHmmss")
										.format(new Date()) + "." + format);
				try {
					ImageIO.write(get, format, file);
					JOptionPane.showMessageDialog(null,
							"成功截图,文件存放在:" + file.getCanonicalPath());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	public BufferedImage getGet() {
		return get;
	}

	public void setGet(BufferedImage get) {
		this.get = get;
	}

	public void mouseWheelMoved(MouseWheelEvent e) {
		int wheelRotation = e.getWheelRotation();// 鼠标滚轮向前转-1,向后转+1
		times += wheelRotation;
		times = times > 0 ? 0 : times;
		times = times < -9 ? -9 : times;

		if (times < 0) {// 负数表示当前为放大
			int tempTimes = Math.abs(times);
			// 获得缩放中心点在srcBi中的实际距离
			xL = (int) ((double) e.getX() * (double) srcBi.getWidth() / (double) this
					.getWidth());
			yA = (int) ((double) e.getY() * (double) srcBi.getHeight() / (double) this
					.getHeight());

			if (w != 0) {
				xL = (int) ((double) e.getX() / (double) this.getWidth() * w + x);
				yA = (int) ((double) e.getY() / (double) this.getHeight() * h + y);
			}
			xR = srcBi.getWidth() - xL;
			yB = srcBi.getHeight() - yA;
			System.out.println("初始点位(xL、yA、xR、yB):" + xL + " " + yA + " " + xR
					+ " " + yB);
			x = xL * tempTimes / 10;
			y = yA * tempTimes / 10;
			w = srcBi.getWidth() - x - xR * tempTimes / 10;
			h = srcBi.getHeight() - y - yB * tempTimes / 10;
			System.out.println("放大倍数:" + times + "截图区域x,y,w,h:" + x + " " + y
					+ " " + w + " " + h);
			bi = srcBi.getSubimage(x, y, w, h);
		} else {
			bi = srcBi;
		}
		this.repaint();
	}

}

enum States {
	NORTH_WEST(new Cursor(Cursor.NW_RESIZE_CURSOR)), NORTH(new Cursor(
			Cursor.N_RESIZE_CURSOR)), NORTH_EAST(new Cursor(
			Cursor.NE_RESIZE_CURSOR)), EAST(new Cursor(Cursor.E_RESIZE_CURSOR)), SOUTH_EAST(
			new Cursor(Cursor.SE_RESIZE_CURSOR)), SOUTH(new Cursor(
			Cursor.S_RESIZE_CURSOR)), SOUTH_WEST(new Cursor(
			Cursor.SW_RESIZE_CURSOR)), WEST(new Cursor(Cursor.W_RESIZE_CURSOR)), MOVE(
			new Cursor(Cursor.MOVE_CURSOR)), DEFAULT(new Cursor(
			Cursor.DEFAULT_CURSOR));

	private Cursor cs;

	States(Cursor cs) {
		this.cs = cs;
	}

	public Cursor getCursor() {
		return cs;
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值