2010-08-18 35 views
98

我有一個有很多bufferedimages的對象,我想創建一個新的對象,將所有的bufferedimages複製到新的對象中,但這些新的圖像可能會被改變,我不想通過改變新的對象圖像來改變原始對象圖像。你如何克隆一個BufferedImage

是否清楚?

這是可能做到的,任何人都可以提出一個好方法嗎? 我想到了getSubImage,但在某處看到,對子圖像的任何更改都會重新選回父圖像。

我只是希望能夠得到一個BufferedImage

+1

不能調用'的clone()'方法?或者我錯過了什麼?我對「BufferedImage」類 – 2010-08-18 16:15:27

+1

的克隆只提供了淺拷貝,因此它將包含對緩存圖像的引用;不是他們的副本。 – 2010-08-18 16:19:13

+7

@NoelM,UltimateGobblement:'BufferedImage'不實現'Cloneable','clone()'方法保護訪問。 – Robert 2012-08-20 16:19:01

回答

147

這樣的事情?

static BufferedImage deepCopy(BufferedImage bi) { 
ColorModel cm = bi.getColorModel(); 
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); 
WritableRaster raster = bi.copyData(null); 
return new BufferedImage(cm, raster, isAlphaPremultiplied, null); 
} 
+2

謝謝使用這一個來複制我的bufferedimage – f1wade 2010-08-20 08:25:04

+3

我也借我的程序=) – BlackSheep 2012-03-10 16:11:59

+0

沒有爲我工作!複製結束了一個像素更寬。 – 2013-10-17 12:07:23

2

這對我使用畫東西的程序出奇有用的,由於對堆棧是幾乎同樣的事情BufferedImages無法實現撤銷/重做狀態。

順便說一句,我建議一路使用這些操作的幾個堆棧! 每次你做的事,馬上創建一個新的形象,使用以上

image = deepCopy((BufferedImage) stackUndo.peek()); 

提到deepcopy的方法改變形象,請你,那麼當你停止編輯(當您鬆開鼠標按鈕等)做

stackUndo.push(image);                                  

,並總是在離開堆棧的頂部

g.drawImage(stackUndo.peek(),x,y,null); 

烤漆元素,然後如果你做一些撤銷/重做操作,遵循東西這樣

public void undoOrRedo(String op) { 
    if(op.equals("undo") && stackUndo.size()>1){ 
     stackRedo.push(stackUndo.pop()); 
     repaint(); 
    } 
    if(op.equals("redo") && stackRedo.size()>0){ 
     stackUndo.push(stackRedo.pop()); 
     repaint(); 
    } 
} 

一定要始終在左側堆棧留下的東西,因爲它畫將始終使用元素在頂部(PEEK)吧!

34

我這樣做:

public static BufferedImage copyImage(BufferedImage source){ 
    BufferedImage b = new BufferedImage(source.getWidth(), source.getHeight(), source.getType()); 
    Graphics g = b.getGraphics(); 
    g.drawImage(source, 0, 0, null); 
    g.dispose(); 
    return b; 
} 

它的工作原理相當好,這是簡單易用。

+2

這看起來很簡單。爲什麼這不是最好的答案?有沒有我不知道的缺陷? – WVrock 2015-02-24 08:53:47

+2

@WVrock如果圖像類型爲0(自定義) – 2016-02-01 12:34:27

+1

替換它不起作用圖形g = b.getGraphics();通過 Graphics2D g = b.createGraphics(); 它是完美的 – Nadir 2016-12-17 17:08:52

13

前面提到的過程在應用於子圖像時失敗。這裏是一個更完整的解決方案:

public static BufferedImage deepCopy(BufferedImage bi) { 
    ColorModel cm = bi.getColorModel(); 
    boolean isAlphaPremultiplied = cm.isAlphaPremultiplied(); 
    WritableRaster raster = bi.copyData(bi.getRaster().createCompatibleWritableRaster()); 
    return new BufferedImage(cm, raster, isAlphaPremultiplied, null); 
} 
1

另一種方法是使用Graphics2D類的圖像繪製到一個新的空白圖像。這並不能真正克隆圖像,但會產生正在生成的圖像的副本。

public static final BufferedImage clone(BufferedImage image) { 
    BufferedImage clone = new BufferedImage(image.getWidth(), 
      image.getHeight(), image.getType()); 
    Graphics2D g2d = clone.createGraphics(); 
    g2d.drawImage(image, 0, 0, null); 
    g2d.dispose(); 
    return clone; 
} 
0

我知道這個問題是很老,但對於未來的遊客,這裏的解決方案,我會使用:

Image oldImage = getImage(); 
Image newImage = oldImage.getScaledInstance(oldImage.getWidth(null), oldImage.getHeight(null), Image.SCALE_DEFAULT); 

請糾正我,如果改變了剛剛獲得的newImage也影響了原始圖像以任何方式。
- >Javadoc for getScaledInstance
- >Javadoc for SCALE_DEFAULT(其他常數列僅低於一個)

+0

我認爲這實際上不會複製圖像,即如果你改變了原來的縮放willalso改變,但它已經有一段時間了,讓別人肯定地說。 – f1wade 2016-12-14 22:20:00