java copy clone bufferedimage

java - ¿Cómo se clona una imagen Buffered?



copy clone (7)

Tengo un objeto que tiene muchas imágenes almacenadas, quiero crear un nuevo objeto copiando todas las imágenes almacenadas en el nuevo objeto, pero estas nuevas imágenes pueden ser alteradas y no quiero que las imágenes originales del objeto se alteren alterando el nuevas imágenes de objetos.

¿Está claro?

¿Es esto posible y alguien puede sugerir una buena manera de hacerlo, por favor? He pensado en getSubImage pero leí en alguna parte que cualquier cambio en la subimagen se vuelve a seleccionar en la imagen principal.

Solo quiero poder obtener una copia completamente nueva o clonar una Imagen Buffered


¿Algo como esto?

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



El procedimiento mencionado anteriormente falla cuando se aplica a imágenes secundarias. Aquí hay una solución más 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); }


Esto fue increíblemente útil para un programa que estoy usando para dibujar cosas, y no pude implementar los estados Deshacer / Rehacer debido a que BufferedImages en las pilas era prácticamente lo mismo.

Por cierto, sugiero todo el camino usando un par de pilas para este tipo de operaciones. Cada vez que haces algo, crea inmediatamente una nueva imagen, utiliza el método deepCopy mencionado anteriormente

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

modifique la imagen como lo desee, luego, cuando deje de editar (como cuando suelta el botón del mouse)

stackUndo.push(image);                            

y siempre pinta el elemento en la parte superior de la pila izquierda

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

y luego si realizas alguna operación de deshacer / rehacer, sigue algo como esto

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

asegúrese de dejar siempre algo en la pila de la izquierda, porque para pintar, ¡siempre usará el elemento en la parte superior (peek)!


Hago esto:

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

Funciona bastante bien y es simple de usar.


Otra forma es usar la clase Graphics2D para dibujar la imagen en una nueva imagen en blanco. Esto realmente no clona la imagen, pero da como resultado una copia de la imagen que se está produciendo.

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


Sé que esta pregunta es bastante antigua, pero para los futuros visitantes, esta es la solución que usaría:

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

newImage si el cambio de la newImage imagen recién obtenida también afecta la imagen original de alguna manera.
-> Javadoc para getScaledInstance
-> Javadoc para SCALE_DEFAULT (las otras constantes se enumeran justo debajo de esa)