Come si clona una BufferedImage

Ho un object che contiene molte immagini bufferizzate, voglio creare un nuovo object copiando tutte le immagini memorizzate nel nuovo object, ma queste nuove immagini potrebbero essere alterate e non voglio che le immagini dell’object originale vengano alterate alterando il nuove immagini di oggetti.

è chiaro?

È ansible farlo e qualcuno 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 nuova copia completamente separata o un clone di una BufferedImage

Qualcosa come questo?

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

Lo faccio:

 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.

La procedura menzionata in precedenza ha esito negativo quando viene 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); } 

Class BufferedImage non implementa l’interfaccia Cloneable. Quindi il metodo clone non è sovrascritto. Ecco un’alternativa per una tecnica di copia profonda: Java Suggerimento 76: un’alternativa alla tecnica di copia profonda

Un altro modo è usare la class 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; } 

Questo è stato insanamente utile per un programma che sto usando per disegnare cose, e non è stato in grado di implementare gli stati Undo / Redo a causa del fatto che BufferedImages sugli Stacks fosse praticamente la stessa cosa.

A proposito, ti suggerisco di usare un paio di pile per questo tipo di operazioni! Ogni volta che fai qualcosa, crea immediatamente una nuova immagine, usa il metodo deepCopy sopra menzionato

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

alterare l’immagine a piacere, quindi quando si interrompe la modifica (come quando si rilascia il pulsante del mouse), fare

 stackUndo.push(image); 

e dipingi sempre l’elemento in cima alla pila di sinistra

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

e se esegui un’operazione di annullamento / ripristino, segui qualcosa di simile

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

assicurati di lasciare sempre qualcosa nella pila di sinistra, perché per la pittura userà sempre l’elemento in alto (sbirciatina)!

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

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

Per favore correggimi se la modifica della nuova immagine appena ottenuta newImage anche sull’immagine originale in alcun modo.
-> Javadoc per getScaledInstance
-> Javadoc per SCALE_DEFAULT (le altre costanti sono elencate appena sotto quella)