我有一个对象,其中有许多缓冲图像,我想创建一个新的对象将所有缓冲图像复制到新对象,但这些新图像可能会被更改,我不希望通过更改原始对象图像来更改新物体图像 .
明白了吗?
这可能吗,有人可以建议一个好方法吗?我已经想到了getSubImage,但是在某处读取了对子图像的任何更改都被重新选回到父图像 .
我只是希望能够获得一个新的完全独立的BufferedImage副本或克隆
我这样做:
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; }
它工作得很好,使用起来很简单 .
应用于子图像时,前面提到的过程失败 . 这是一个更完整的解决方案:
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接口 . 因此克隆方法不会被覆盖 . 这是深度复制技术的替代方案:Java Tip 76: An alternative to the deep copy technique
像这样的东西?
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); }
另一种方法是使用 Graphics2D 类将图像绘制到新的空白图像上 . 这并不能真正克隆图像,但会产生正在生成的图像的副本 .
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; }
这对于我用来绘制内容的程序非常有用,并且由于Stacks上的BufferedImages实际上是相同的东西而无法实现Undo / Redo状态 .
顺便说一句,我建议使用几个堆栈进行这些操作!每次执行某些操作时,立即创建新图像,使用上面提到的deepCopy方法
image = deepCopy((BufferedImage) stackUndo.peek());
随你改变图像,然后当你停止编辑时(比如当你松开鼠标按钮时)
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(); } }
一定要在左侧堆栈中留下一些东西,因为对于绘画它总是会使用它顶部的元素(窥视)!
我知道这个问题很老了,但对于未来的访问者来说,这是我使用的解决方案:
Image oldImage = getImage(); Image newImage = oldImage.getScaledInstance(oldImage.getWidth(null), oldImage.getHeight(null), Image.SCALE_DEFAULT);
如果更改刚刚获得的 newImage 也会以任何方式影响原始图像,请更正我 .
newImage
Javadoc for getScaledInstance
Javadoc for SCALE_DEFAULT(其他常量列在那一个下面)
7 回答
我这样做:
它工作得很好,使用起来很简单 .
应用于子图像时,前面提到的过程失败 . 这是一个更完整的解决方案:
BufferedImage类不实现Cloneable接口 . 因此克隆方法不会被覆盖 . 这是深度复制技术的替代方案:Java Tip 76: An alternative to the deep copy technique
像这样的东西?
另一种方法是使用
Graphics2D
类将图像绘制到新的空白图像上 . 这并不能真正克隆图像,但会产生正在生成的图像的副本 .这对于我用来绘制内容的程序非常有用,并且由于Stacks上的BufferedImages实际上是相同的东西而无法实现Undo / Redo状态 .
顺便说一句,我建议使用几个堆栈进行这些操作!每次执行某些操作时,立即创建新图像,使用上面提到的deepCopy方法
随你改变图像,然后当你停止编辑时(比如当你松开鼠标按钮时)
并始终将元素绘制在左侧堆栈的顶部
然后如果你做一些撤消/重做操作,请按照这样的方法
一定要在左侧堆栈中留下一些东西,因为对于绘画它总是会使用它顶部的元素(窥视)!
我知道这个问题很老了,但对于未来的访问者来说,这是我使用的解决方案:
如果更改刚刚获得的
newImage
也会以任何方式影响原始图像,请更正我 .