How do you clone a BufferedImage

非 Y 不嫁゛ 提交于 2019-11-26 11:46:27

Something like this?

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

I do this:

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

It works fairly well and it is simple to use.

The previously mentioned procedure fails when applied to sub images. Here is a more complete solution:

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 does not implement the Cloneable interface. Thus the clone method is not overriden. Here's an alternative for a deep copy technique: Java Tip 76: An alternative to the deep copy technique

Another way is to use the Graphics2D class to draw the image onto a new blank image. This doesn't really clone the image, but it results in a copy of the image being produced.

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

I know that this question is pretty old, but for future visitors, here's the solution I'd use:

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

Please correct me if changing the just obtained newImage also affects the original image in any way.
--> Javadoc for getScaledInstance
--> Javadoc for SCALE_DEFAULT (the other constants are listed just below that one)

Santiago Zubieta

This was insanely useful for a program that I'm using to draw stuff, and was unable to implement Undo/Redo states due to BufferedImages on the Stacks being virtually the same thing.

By the way, I suggest all the way using a couple of stacks for these kind of operations! Everytime you do something, immediately create a new image, use the deepCopy method mentioned above

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

alter the image as you please, then when you stop editing (like when you release the mouse button) do

stackUndo.push(image);                                                   

and always paint the element at the top of the left stack

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

and then if you do some undo/redo operation, follow something like this

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

be sure to always left something in the left stack, because for painting it will always use the element at the top (peek) of it!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!