如何在Java中裁剪图像?

我想用鼠标手动裁剪图像。
假设图像有一些文字,我想从图像中select一些文字,那么为了这个目的,我想用鼠标剪裁这个区域。

我发现最有用的裁剪缓冲图像的解决scheme使用getSubImage(x,y,w,h);

我的裁剪程序最终看起来像这样:

private BufferedImage cropImage(BufferedImage src, Rectangle rect) { BufferedImage dest = src.getSubimage(0, 0, rect.width, rect.height); return dest; } 

这个问题的主要答案有两个潜在的主要问题。 首先,按照文档:

public BufferedImage getSubimage(int x,int y,int w,int h)

返回由指定的矩形区域定义的子图像。 返回的BufferedImage与原始图像共享相同的数据数组。

实质上,这意味着getSubimage的结果是指向原始图像的一个子节点的指针。

为什么这很重要? 那么,如果您打算由于任何原因而编辑子图像,编辑也会发生在原始图像上。 例如,当我在一个单独的窗口中使用较小的图像放大原始图像时,遇到了这个问题。 (有点像放大镜)。 我可以倒置颜色来更容易地看到某些细节,但“缩放”的区域在原始图像中也是倒立的! 所以有一小部分原始图像反转了颜色,其余部分保持正常。 在许多情况下,这并不重要,但是如果您想要编辑图像,或者只是想要裁剪的部分的副本,则可能需要考虑一种方法。

这给我们带来了第二个问题。 幸运的是,这并不像第一个那么大。 getSubImage与原始图像共享相同的数据数组。 这意味着整个原始图像仍然存储在内存中。 假设通过“裁剪”图像,你实际上想要一个较小的图像,你将需要重新绘制一个新的图像,而不是只是得到子图像。

尝试这个:

 BufferedImage img = image.getSubimage(startX, startY, endX, endY); //fill in the corners of the desired crop location here BufferedImage copyOfImage = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics g = copyOfImage.createGraphics(); g.drawImage(img, 0, 0, null); return copyOfImage; //or use it however you want 

这种技术可以让你自己寻找裁剪后的图像,而不需要链接回原始图像。 这将保持原始图像的完整性,并节省存储较大图像的内存开销。 (如果您稍后转储原始图像)

这是一个可行的方法:

 import javax.image.BufferedImage; // I think import java.awt.Rectangle; import java.awt.Color; import java.awt.Graphics; public BufferedImage crop(BufferedImage src, Rectangle rect) { BufferedImage dest = new BufferedImage(rect.getWidth(), rect.getHeight(), BufferedImage.TYPE_ARGB_PRE); Graphics g = dest.getGraphics(); g.drawImage(src, 0, 0, rect.getWidth(), rect.getHeight(), rect.getX(), rect.getY(), rect.getX() + rect.getWidth(), rect.getY() + rect.getHeight(), null); g.dispose(); return dest; } 

当然,你必须制作你自己的JComponent:

 import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import javax.image.BufferedImage; import java.awt.Rectangle; import java.awt.Graphics; import javax.swing.JComponent; public class JImageCropComponent extends JComponent implements MouseListener, MouseMotionListener { private BufferedImage img; private int x1, y1, x2, y2; public JImageCropComponent(BufferedImage img) { this.img = img; this.addMouseListener(this); this.addMouseMotionListener(this); } public void setImage(BufferedImage img) { this.img = img; } public BufferedImage getImage() { return this; } @Override public void paintComponent(Graphics g) { g.drawImage(img, 0, 0, this); if (cropping) { // Paint the area we are going to crop. g.setColor(Color.RED); g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2)); } } @Override public void mousePressed(MouseEvent evt) { this.x1 = evt.getX(); this.y1 = evt.getY(); } @Override public void mouseReleased(MouseEvent evt) { this.cropping = false; // Now we crop the image; // This is the method a wrote in the other snipped BufferedImage cropped = crop(new Rectangle(Math.min(x1, x2), Math.min(y1, y2), Math.max(x1, x2), Math.max(y1, y2)); // Now you have the cropped image; // You have to choose what you want to do with it this.img = cropped; } @Override public void mouseDragged(MouseEvent evt) { cropping = true; this.x2 = evt.getX(); this.y2 = evt.getY(); } //TODO: Implement the other unused methods from Mouse(Motion)Listener } 

我没有testing它。 也许有一些错误(我不知道所有的import)。

你可以把crop(img, rect)方法放在这个类中。 希望这可以帮助。

这个问题没有足够的信息来回答。 一个通用的解决scheme(取决于你的GUI框架):添加一个鼠标事件处理程序,将捕捉点击和鼠标移动。 这会给你你的(x,y)坐标。 接下来使用这些坐标来裁剪图像。

 File fileToWrite = new File(filePath, "url"); BufferedImage bufferedImage = cropImage(fileToWrite, x, y, w, h); private BufferedImage cropImage(File filePath, int x, int y, int w, int h){ try { BufferedImage originalImgage = ImageIO.read(filePath); BufferedImage subImgage = originalImgage.getSubimage(x, y, w, h); return subImgage; } catch (IOException e) { e.printStackTrace(); return null; } } 

您需要阅读Java Image API和与鼠标相关的API,也许在awt.event软件包下的某处。

首先,你需要能够加载和显示图像到屏幕上,也许你会使用JPanel。

然后从那里,你将尝试实现一个鼠标运动监听器接口和其他相关的接口。 也许你会被绑在mouseDragged方法上…

对于mousedragged动作,您将通过拖动来获得矩形窗体的坐标。

然后从这些坐标中,您将从您的图像中获得子图像,并重新重新绘制它。

然后显示裁剪的图像…我不知道这是否会起作用,只是我的想象力的产物…只是一个想法!