2010-03-05 67 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; 
    } 
}