2010-08-18 9 views
98

J'ai un objet qui contient de nombreuses images tamponnées, je veux créer un nouvel objet en copiant toutes les images tamponnées dans le nouvel objet, mais ces nouvelles images peuvent être modifiées et je ne veux pas que le images d'objet original à modifier en modifiant les images des nouveaux objets.Comment cloner une image tamponnée

est-ce clair?

Est-ce possible et est-ce que quelqu'un peut suggérer un bon moyen de le faire s'il vous plaît? J'ai pensé à getSubImage mais j'ai lu quelque part que les modifications apportées à la sous-image sont renvoyées à l'image parente.

Je veux juste être en mesure d'obtenir une nouvelle copie entièrement séparée ou clone d'une classe BufferedImage

+1

ne peut pas vous appeler la méthode 'clone()'? Ou ai-je manqué quelque chose? Je ne connais pas grand-chose à propos de la classe 'BufferedImage' –

+1

clone fournit seulement une copie superficielle afin qu'il contienne les références aux images tamponnées; pas de copies d'eux. –

+7

@NoelM, UltimateGobblement: 'BufferedImage' n'implémente pas Cloneable et la méthode' clone() 'a un accès protégé. – Robert

Répondre

147

Quelque chose comme ça?

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

merci ive utilisé celui-ci pour copier mon image tamponnée – f1wade

+3

J'emprunte aussi ceci dans mon programme =) – BlackSheep

+0

N'a pas fonctionné pour moi! La copie a fini par un pixel plus large. –

2

Ce fut incroyablement utile pour un programme que j'utilise pour dessiner des choses, et n'a pas pu mettre en œuvre Undo/Redo États en raison de BufferedImages sur le empilements étant pratiquement la même chose. A propos, je suggère tout le chemin en utilisant quelques piles pour ce genre d'opérations! Chaque fois que vous faites quelque chose, créer immédiatement une nouvelle image, utilisez la méthode deepCopy mentionné ci-dessus

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

modifier l'image que vous s'il vous plaît, lorsque vous arrêtez l'édition (comme lorsque vous relâchez le bouton de la souris) faire

stackUndo.push(image);                                  

et toujours peindre l'élément en haut de la pile gauche

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

et si vous faites une opération undo/redo, suivre quelque chose comme celui-ci

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

assurez-vous de toujours laissé quelque chose dans la pile gauche, parce que pour la peinture, il utilisera toujours l'élément en haut (coup d'oeil) de celui-ci!

34

Je fais ceci:

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

Il fonctionne assez bien et il est simple à utiliser.

+2

Cela semble assez simple. Pourquoi ce n'est pas la meilleure réponse? Y a-t-il un défaut dont je ne suis pas au courant? – WVrock

+2

@WVrock Cela ne fonctionne pas si le type d'image est 0 (personnalisé) –

+1

remplacez Graphics g = b.getGraphics(); par Graphics2D g = b.createGraphics(); et c'est parfait – Nadir

13

La procédure mentionnée précédemment échoue lorsqu'elle est appliquée aux sous-images. Voici une solution plus complète:

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

Une autre façon est d'utiliser la classe Graphics2D pour dessiner l'image sur une nouvelle image vierge. Cela ne clone pas vraiment l'image, mais il en résulte une copie de l'image produite.

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

Je sais que cette question est assez vieux, mais pour les futurs visiteurs, voici la solution que je utiliser:

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

S'il vous plaît me corriger si le changement juste obtenu newImage affecte également l'image d'origine de quelque manière que.
->Javadoc for getScaledInstance
->Javadoc for SCALE_DEFAULT (les autres constantes sont énumérées juste au-dessous que l'on)

+0

Je pense que cela ne copiera pas réellement l'image, c'est-à-dire que si vous avez changé l'original, l'échelle changera également, mais cela fait un moment si mal que quelqu'un d'autre le dise. – f1wade

Questions connexes