你如何克隆一个BufferedImage
我有一个有许多bufferedimages的对象,我想创build一个新的对象,将所有的bufferedimages拷贝到新的对象中,但这些新的图像可能会被改变,我不希望原始的对象图像被改变新的对象图像。
这是清楚的吗?
这是可能做到的,任何人都可以提出一个好的方法来做到这一点吗? 我曾经想过getSubImage,但是读到的地方是,任何对子图像的改变都会被重新选回父图像。
我只是想能够得到一个新的完全分离的复制或克隆的BufferedImage
像这样的东西?
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); }
我这样做:
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; }
它工作得很好,使用起来很简单。
前面提到的过程在应用于子图像时失败。 这是一个更完整的解决scheme:
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); }
BufferedImage类没有实现Cloneable接口。 因此克隆方法没有被覆盖。 以下是深层复制技术的替代scheme: Java技巧76:深度复制技术的替代scheme
这对于我用来绘制内容的程序是非常有用的,由于Stacks上的BufferedImages实际上是一样的,所以无法实现Undo / Redo状态。
顺便说一句,我build议一路使用这些操作的几个堆栈! 每次你做一些事情,立即创build一个新的图像,使用上面提到的deepCopy方法
image = deepCopy((BufferedImage) stackUndo.peek());
改变你的图像,然后当你停止编辑(如当你释放鼠标button)做
stackUndo.push(image);
并始终在左侧堆栈顶部绘制元素
g.drawImage(stackUndo.peek(),x,y,null);
然后如果你做一些撤销/重做操作,按照这样的事情
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(); } }
一定要在左边的堆栈中留下一些东西,因为绘画的时候总是使用顶部的元素(peek)!
另一种方法是使用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; }
我知道这个问题是相当古老的,但对于未来的访问者,这里是我使用的解决scheme:
Image oldImage = getImage(); Image newImage = oldImage.getScaledInstance(oldImage.getWidth(null), oldImage.getHeight(null), Image.SCALE_DEFAULT);
如果更改刚刚获得的newImage
也会以任何方式影响原始图像,请纠正我。
– > 为getScaledInstance的Javadoc
– > Javadoc for SCALE_DEFAULT (其他常数在下面列出)