首页 文章

你如何克隆BufferedImage

提问于
浏览
105

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

明白了吗?

这可能吗,有人可以建议一个好方法吗?我已经想到了getSubImage,但是在某处读取了对子图像的任何更改都被重新选回到父图像 .

我只是希望能够获得一个新的完全独立的BufferedImage副本或克隆

7 回答

  • 17

    我这样做:

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

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

  • 1

    应用于子图像时,前面提到的过程失败 . 这是一个更完整的解决方案:

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

    BufferedImage类不实现Cloneable接口 . 因此克隆方法不会被覆盖 . 这是深度复制技术的替代方案:Java Tip 76: An alternative to the deep copy technique

  • 39

    像这样的东西?

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

    另一种方法是使用 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;
    }
    
  • 1

    这对于我用来绘制内容的程序非常有用,并且由于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();
        }
    }
    

    一定要在左侧堆栈中留下一些东西,因为对于绘画它总是会使用它顶部的元素(窥视)!

  • 4

    我知道这个问题很老了,但对于未来的访问者来说,这是我使用的解决方案:

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

    如果更改刚刚获得的 newImage 也会以任何方式影响原始图像,请更正我 .

相关问题