2010-08-18 12 views
98

Ho un oggetto che ha molti bufferedimages in esso, voglio creare un nuovo oggetto copiare tutti i bufferedimages nel nuovo oggetto, ma queste nuove immagini possono essere modificate e non voglio che la le immagini dell'oggetto originale da modificare alterando le nuove immagini degli oggetti.Come si fa a clonare un BufferedImage

è chiaro?

Questo è possibile fare e chiunque può suggerire un buon modo per farlo per favore? Ho pensato a getSubImage ma ho letto da qualche parte che qualsiasi modifica all'immagine secondaria è rimessa all'immagine principale.

voglio solo essere in grado di ottenere una copia completamente separata dolce o clone di un BufferedImage

+1

non si può chiamare) il metodo ('' il clone? O mi sono perso qualcosa? Non conosco molto sulla classe 'BufferedImage' –

+1

clone fornisce solo una copia superficiale, quindi conterrebbe i riferimenti alle immagini bufferizzate; non copie di loro. –

+7

@NoelM, UltimateGobblement: 'BufferedImage' non implementa' Cloneable' e il metodo 'clone()' ha accesso protetto. – Robert

risposta

147

Qualcosa di simile?

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

grazie ho usato questo per copiare il mio bufferedimage – f1wade

+3

Sto anche prendendo in prestito questo nel mio programma =) – BlackSheep

+0

Non ha funzionato per me! La copia ha finito con un pixel più largo. –

2

Questa era follemente utile per un programma che sto usando per disegnare roba, e non era in grado di implementare Undo/Redo stati a causa BufferedImages sul Stacks essere praticamente la stessa cosa.

A proposito, vi consiglio di tutta la strada con un paio di pile per questo tipo di operazioni! Ogni volta che fate qualcosa, creare immediatamente una nuova immagine, utilizzare il metodo deepcopy di cui sopra

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

alterare l'immagine come ti pare, poi, quando si smette di editing (come quando si rilascia il pulsante del mouse) fare

stackUndo.push(image);                                  

e sempre dipingere l'elemento in cima alla pila sinistra

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

e poi se non un po 'di annullare il funzionamento/redo, seguire qualcosa Ti piace questa

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(); 
    } 
} 

essere sicuri di sinistra sempre qualcosa nello stack di sinistra, perché per la pittura sarà sempre utilizzare l'elemento in alto (PEEK) di esso!

34

faccio questo:

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

Funziona abbastanza bene ed è semplice da usare.

+2

Sembra molto semplice. Perché questa non è la migliore risposta? C'è un difetto di cui non sono a conoscenza? – WVrock

+2

@WVrock Non funziona se il tipo di immagine è 0 (personalizzato) –

+1

Sostituisci Graphics g = b.getGraphics(); di Graphics2D g = b.createGraphics(); ed è perfetto – Nadir

13

La procedura descritta in precedenza non riesce quando applicata alle immagini secondarie. Ecco una soluzione più completa:

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

Un altro modo è quello di utilizzare la classe Graphics2D per disegnare l'immagine su una nuova immagine vuota. Questo in realtà non clonerà l'immagine, ma si tradurrà in una copia dell'immagine prodotta.

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

So che questa domanda è piuttosto vecchio, ma per i futuri visitatori, ecco la soluzione userei:

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

Si prega di correggere se cambiando l'appena ottenuto newImage colpisce anche l'immagine originale in ogni modo.
->Javadoc for getScaledInstance
->Javadoc for SCALE_DEFAULT (le altre costanti sono elencate appena sotto quello)

+0

Penso che in realtà non copierebbe l'immagine, cioè se hai cambiato l'originale anche la scala cambierà, ma è stato un po 'così male che qualcun altro possa dire di sicuro. – f1wade