Java 你如何克隆一个 BufferedImage

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3514158/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 01:26:02  来源:igfitidea点击:

How do you clone a BufferedImage

javacopyclonebufferedimage

提问by f1wade

I have an object which has many bufferedimages in it, I want to create a new object copying all the bufferedimages into the new object, but these new images may be altered and i don't want the original object images to be altered by altering the new objects images.

我有一个包含许多缓冲图像的对象,我想创建一个新对象,将所有缓冲图像复制到新对象中,但是这些新图像可能会被更改,我不希望通过更改原始对象图像来更改新对象图像。

is that clear?

明白了吗?

Is this possible to do and can anyone suggest a good way to do it please? I have thought of getSubImage but read somewhere that any changes to the subimage are relected back to the parent image.

这是可能的,有人可以建议一个好的方法吗?我想过 getSubImage 但在某处读到对子图像的任何更改都会反映回父图像。

I just want to be able to get a fresh entirely separate copy or clone of a BufferedImage

我只想能够获得 BufferedImage 的全新的完全独立的副本或克隆

采纳答案by Klark

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

回答by Mike

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

类 BufferedImage 没有实现 Cloneable 接口。因此,不会覆盖克隆方法。这是深拷贝技术的替代方案: Java 技巧 76:深拷贝技术的替代方案

回答by 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.

这对于我用来绘制东西的程序非常有用,并且由于堆栈上的 BufferedImages 几乎是同一件事而无法实现撤消/重做状态。

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

顺便说一句,我建议一直使用几个堆栈来进行此类操作!每次做某事,立即创建一个新图像,使用上面提到的 deepCopy 方法

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!

确保始终在左侧堆栈中留下一些东西,因为对于绘画,它将始终使用顶部(查看)的元素!

回答by 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.

它工作得很好,使用起来也很简单。

回答by user1050755

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

回答by HyperNeutrino

Another way is to use the Graphics2Dclass 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.

另一种方法是使用Graphics2D该类将图像绘制到新的空白图像上。这不会真正克隆图像,但会生成图像的副本。

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

回答by PixelMaster

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 newImagealso affects the original image in any way.
--> Javadoc for getScaledInstance
--> Javadoc for SCALE_DEFAULT(the other constants are listed just below that one)

如果更改刚刚获得newImage的图像也会以任何方式影响原始图像,请纠正我。
--> getScaledInstance 的 Javadoc
--> SCALE_DEFAULT 的 Javadoc(其他常量列在该常量的正下方)