2010-08-18 18 views
98

Tengo un objeto que tiene muchas imágenes almacenadas en él, 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 el las imágenes originales del objeto se alterarán alterando las nuevas imágenes de los objetos.Cómo clonar una Imagen Buffered

¿Está claro?

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

Sólo quiero ser capaz de obtener una nueva copia completamente separado o clon de un Clase BufferedImage BufferedImage

+1

No se puede llamar a la 'clon)' método (? ¿O me he perdido algo? No sé mucho sobre la clonación de la clase 'BufferedImage' –

+1

; el clon solo proporciona una copia poco profunda, por lo que contendría las referencias a las imágenes almacenadas en el búfer; no copias de ellos. –

+7

@NoelM, UltimateGobblement: 'BufferedImage' no implementa' Cloneable' y el método 'clone()' tiene acceso protegido. – Robert

Respuesta

147

¿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); 
} 
+2

gracias he usado este para copiar mi imagen en el buffer – f1wade

+3

También estoy tomando prestado esto en mi programa =) – BlackSheep

+0

¡No funcionó para mí! La copia terminó un píxel más ancho. –

2

Esto fue increíblemente útil para un programa que estoy usando para dibujar cosas, y era incapaz de implementar deshacer/rehacer estados debido a BufferedImages en las pilas siendo prácticamente la misma cosa.

Por cierto, sugiero todo el camino con un par de pilas para este tipo de operaciones. Cada vez que se hace algo, crear inmediatamente una nueva imagen, utilice el método deepCopy mencionado anteriormente

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

alterar la imagen a su gusto, a continuación, cuando se deja de edición (como cuando se suelta el botón del ratón) hacer

stackUndo.push(image);                                  

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

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

y luego si alguna operación de deshacer/rehacer, siga 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 siempre dejado algo en la pila de la izquierda, porque para pintarlo siempre utilizará el elemento en la parte superior (PEEK) de él!

34

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 fácil de usar.

+2

Esto se ve bastante simple. ¿Por qué esta no es la mejor respuesta? ¿Hay algún defecto del que no tengo conocimiento? – WVrock

+2

@WVrock No funciona si el tipo de imagen es 0 (personalizado) –

+1

reemplace Graphics g = b.getGraphics(); por Graphics2D g = b.createGraphics(); y es perfecto – Nadir

13

El procedimiento mencionado anteriormente falla cuando se aplica a las imágenes secundarias. Aquí es 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); 
} 
1

Otra forma es utilizar 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; 
} 
0

Sé que esta pregunta es bastante viejo, pero para los futuros visitantes, aquí está la solución que haría uso:

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

Por favor, corríjanme si el cambio de la que acabamos de obtener newImage también afecta a la imagen original de cualquier manera.
->Javadoc for getScaledInstance
->Javadoc for SCALE_DEFAULT (las otras constantes se enumeran justo debajo de aquél)

+0

Creo que en realidad no copiaría la imagen, es decir, si cambió el original, la escala también cambiará, pero ha pasado un tiempo tan mal que alguien más dirá con certeza. – f1wade