我想用鼠标手动裁剪图像 假设图像有一些文本,我想从图像中选择一些文本,然后 为此,我想使用鼠标裁剪该区域。
答案 0 :(得分:138)
我发现最适合裁剪缓冲图像的解决方案使用getSubImage(x,y,w,h);
我的裁剪程序最终看起来像这样:
private BufferedImage cropImage(BufferedImage src, Rectangle rect) {
BufferedImage dest = src.getSubimage(0, 0, rect.width, rect.height);
return dest;
}
答案 1 :(得分:37)
这个问题的主要答案有两个潜在的主要问题。首先,根据文档:
public BufferedImage getSubimage(int x, 是的, 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
此技术将为您提供您正在寻找的裁剪图像,而不会将链接返回到原始图像。这将保留原始图像的完整性,并节省存储较大图像的内存开销。 (如果稍后转储原始图像)
答案 2 :(得分:14)
这是一种可行的方法:
import java.awt.image.BufferedImage;
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 java.awt.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
}
我没有测试它。也许有一些错误(我不确定所有的进口)。
您可以将crop(img, rect)
方法放在此类中。
希望这会有所帮助。
答案 3 :(得分:10)
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;
}
}
答案 4 :(得分:6)
这个问题没有足够的信息来回答。一般解决方案(取决于您的GUI框架):添加一个鼠标事件处理程序,它将捕获点击和鼠标移动。这将为您提供(x,y)坐标。接下来使用这些坐标裁剪图像。
答案 5 :(得分:2)
您需要了解Java Image API和与鼠标相关的API,可能在java.awt.event package
下的某处。
首先,您需要能够将图像加载并显示到屏幕,也许您将使用JPanel
。
然后,从那里,您将尝试实现鼠标移动侦听器接口和其他相关接口。也许你会受到mouseDragged
方法的束缚......
对于mousedragged
操作,您将通过拖动...
然后从这些坐标中,您将从您拥有的图像中获取子图像,然后重新绘制它....
然后显示裁剪的图像......我不知道这是否会起作用,只是我想象中的一个产物......只是一个想法!
答案 6 :(得分:0)
我给出这个示例,因为它实际上适用于我的用例。
我正尝试使用 AWS Rekognition API 。 该API返回一个BoundingBox对象:
ScaleX
下面的代码使用它裁剪图像:
RotationX