どのようにBufferedImageを複製しますか


120

多くのバッファリングされたイメージを含むオブジェクトがあります。すべてのバッファリングされたイメージを新しいオブジェクトにコピーする新しいオブジェクトを作成したいのですが、これらの新しいイメージは変更される可能性があり、元のオブジェクトのイメージが新しいオブジェクトの画像。

それは明らかですか?

これは可能ですか?誰もがそれを行うための良い方法を提案できますか?私はgetSubImageについて考えましたが、サブイメージへの変更はすべて親イメージに反映されるとどこかで読みました。

私は、BufferedImageの完全に別個の新しいコピーまたはクローンを取得できるようにしたいだけです。


1
clone()メソッドを呼び出せませんか?または私は何かを逃したのですか?BufferedImageクラスについてはあまり知りません
ノエルM

1
cloneは浅いコピーのみを提供するため、バッファリングされたイメージへの参照が含まれます。それらのコピーではありません。
Ultimate Gobblement 2010

7
@ NoelM、UltimateGobblement:BufferedImage実装されておらずCloneableclone()メソッドはアクセスを保護しています。
ロバート

回答:


173

このようなもの?

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
私はこれも私のプログラムで借りています=)
Daniel Kats

この方法でサブ
イメージの

7
これはほとんどの状況で機能しますが、BufferedImageがトリミングされている場合は正しく機能しません(トリミングされる前の画像全体が返されます)。:これに対する簡単な修正はにその最後の行を変更することです
HaydenStudios

3
新しいBufferedImage(cm、raster、isAlphaPremultiplied、null).getSubimage(0、0、bi.getWidth()、bi.getHeight());を返します。
HaydenStudios 2014年

copyData(null)は、親ラスター(つまり、画像がサブ画像の場合)で機能する可能性があるため、常に機能するとは限りません。変更された回答を参照してください
user1050755

46

私はこれをします:

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

それはかなりうまくいき、使い方は簡単です。


3
これはかなりシンプルに見えます。なぜこれが最善の答えではないのですか?私が気づいていない欠陥はありますか?
WVrock 2015

2
@WVrock画像タイプが0(カスタム)の場合は機能しません
Tilman Hausherr

3
Graphics g = b.getGraphics();を置き換えます。Graphics2Dによってg = b.createGraphics(); そして、それは完璧です
天底

1
これが一番きれいな答えだと思います。これと受け入れられた答えの間にパフォーマンスの違いはありますか?いいえ、無視できると思いますか?オブジェクトの作成がjvmで最適化されているため、これがより速くなる可能性があります。また、openjdk 11を使用しています。誰かがその質問に答えられる場合。
thekevshow

18

前述の手順をサブ画像に適用すると失敗します。これはより完全なソリューションです:

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

ありがとう、サブイメージを複製しようとしてオフセットエラーが発生しました。このバージョンはまさに私が必要としたものです。
rococo

5

別の方法は、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;
}


4

私はこの質問がかなり古いことを知っていますが、将来の訪問者のために、私が使用する解決策は次のとおりです:

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

取得したばかりの変更newImageが元の画像に何らかの影響を与える場合も修正してください。
-> getScaledInstanceのJavadoc-
> SCALE_DEFAULTのJavadoc(他の定数はそのすぐ下にリストされています)


私はそれが実際に画像をコピーしないと思います、すなわちあなたがオリジナルを変更した場合、拡大縮小も変更されますが、それはしばらくの間とても確かに他の誰かに言わせてください。
f1wade 16

1
オリジナルを変更してもコピーは変更されないため、これは実際にイメージをコピーします。この答えは短くて簡潔であり、BufferedImagesにさえ限定されていません。唯一の問題は、それが戻るのImageではなく、戻ることBufferedImageです。
クロウ2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.