2010-03-05 71 views
60

我想使用鼠标手动裁剪图像。
假设图像有一些文字,我想从图像中选择一些文字,然后 为此目的我想通过使用鼠标裁剪该区域。如何在Java中裁剪图像?

+0

下面几个好主意。另请参阅http://java.sun.com/docs/books/tutorial/2d/ – trashgod 2010-03-05 16:23:27

+0

Hussain:给出这些详细的答案之一检查 – IcedDante 2013-01-15 05:15:39

回答

2

您需要阅读Java Image API和与鼠标相关的API,可能位于awt.event包的某处。

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

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

对于动作的mouseDragged,您将获得由拖动矩形形式的坐标...

从这些坐标

然后,你会得到从你有图像的子图像,你有点重新绘制它...

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

+0

感谢您的建议 我如何设置图像在applet上通过使用面板进行裁剪 – Hussain 2010-03-05 11:04:52

6

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

+0

谢谢 我会尝试它 – Hussain 2010-03-05 11:03:40

9

这是将工作的方法:

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 

} 

我没有测试它。也许有一些错误(我不确定所有的进口)。

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

+1

感谢您给予回复 但它会带来很多错误! 你能告诉我一个简单的代码来裁剪图像吗? – Hussain 2010-03-08 03:34:33

123

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

我种植常规最终看上去像这样:

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

为什么不包括x&y坐标。 'BufferedImage dest = src.getSubimage(rect.x,rect.y,rect.width,rect.height);' – Sorter 2013-03-09 08:57:58

29

有与领先的回答这个问题二潜在的重大问题。首先,作为每文档:

公共的BufferedImage getSubimage(INT的x, INT Y, INT瓦特, INT 1H)

返回由指定矩形区域定义一个子图像。 返回的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 

这项技术会给你你是通过自身寻找裁剪后的图像,没有链接返回到原始图像。这样可以保持原始图像的完整性,并且可以节省存储较大图像的内存开销。 (如果稍后转储原始图像)

6
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; 
    } 
}