如何克隆 BufferedImage

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

明白了吗?

这可能做到吗? 有没有人能提出一个好的方法来做到这一点? 我已经想到了 getSubImage,但是在某个地方读到,对子图像的任何更改都会被反射回父图像。

我只是希望能够得到一个完全独立的 BufferedImage 的新拷贝或克隆

65683 次浏览

类 BufferedImage 不实现 Cloneable 接口。因此,克隆方法不会被重写。这里有一个深度拷贝技术的替代方案: Java 技巧76: 深度复制技术的替代方案

像这样吗?

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

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

上面提到的过程在应用到子图像时失败了。下面是一个更完整的解决方案:

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

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

我知道这个问题已经很老了,但是对于未来的访问者,这里有一个我会用到的解决方案:

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

如果改变刚刚获得的 newImage也会以任何方式影响原始图像,请纠正我。
GetScaledInstance% 28int,% 20int,% 20int% 29”rel = “ noReferrer”> Javadoc for getScaledInstance
- > 用于 SCALE _ DEFAULT 的 Javadoc(其他常量在该常量下面列出)

以下使用数组拷贝的解决方案大约是 快3到4倍,而不是公认的答案:

public static BufferedImage copyImage(BufferedImage source){
BufferedImage bi = new BufferedImage(source.getWidth(), source.getHeight(), source.getType());
byte[] sourceData = ((DataBufferByte)source.getRaster().getDataBuffer()).getData();
byte[] biData = ((DataBufferByte)bi.getRaster().getDataBuffer()).getData();
System.arraycopy(sourceData, 0, biData, 0, sourceData.length);
return bi;
}

顺便说一下,使用 Graphics2D 的答案也提供了类似的好结果。

这是我多年前为 JFreeChart 写的一个解决方案。

它还将复制 BufferedImage 中可能存在的任何属性。

我相信这是测试所有已知的颜色模型(图像类型)。

我不知道它是否适用于@Jos éRobertoAraújoJúnior 讨论的 Image Type 0
但是: 图像类型0是无效的,不应该发生。

/**
* Copied from
* <a href=https://github.com/jfree/jfreechart/blob/master/src/main/java/org/jfree/chart/util/PaintAlpha.java>JFreeChart PaintAlpha</a>
*
* @param   srcImage
* @return
*/
public static BufferedImage cloneImage(final BufferedImage srcImage) {


final WritableRaster srcRaster = srcImage.getRaster();
final WritableRaster dstRaster = srcRaster.createCompatibleWritableRaster();
/*
* This is the code that actually COPIES the pixels...
*/
dstRaster.setRect(srcRaster);
/*
* Images hardly ever have Properties, but we copy them anyway...
*/
final String[]                  propNames = srcImage.getPropertyNames();
final Hashtable<String, Object> props;


if (propNames == null) {
props     =  null;
} else {
props     =  new Hashtable<>();


for (int i = 0; i < propNames.length; i++) {
props.put(propNames[i], srcImage.getProperty(propNames[i]));
}
}
/*
* That's it folks! Return the new clone...
*/
return new BufferedImage(srcImage.getColorModel(), dstRaster, srcImage.isAlphaPremultiplied(), props);
}

我做了这个解决方案使用两个功能,它可以工作的每一个可能的图像,甚至由摄像机的笔记本电脑的图像,我面临的问题是,通过摄像机裁剪图像后,它不工作,但这个解决方案将工作

static BufferedImage deepCopy(BufferedImage bi)
{
try
{
ColorModel cm = bi.getColorModel();
boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
WritableRaster raster = bi.copyData(bi.getRaster().createCompatibleWritableRaster());
return new BufferedImage(cm, raster, isAlphaPremultiplied, null);
}
catch(Exception ex)
{
        

}
try{
BufferedImage b = new BufferedImage(bi.getWidth(), bi.getHeight(), bi.getType());
Graphics g = b.getGraphics();
g.drawImage(bi, 0, 0, null);
g.dispose();
return b;
        

}
catch(Exception ex){
        

        

        

}
    

return null;
}