BufferedImage'ı nasıl klonlarsınız


120

İçinde çok sayıda arabellek görüntüleri olan bir nesnem var, tüm arabellek görüntülerini yeni nesneye kopyalayan yeni bir nesne oluşturmak istiyorum, ancak bu yeni görüntüler değiştirilebilir ve orijinal nesne görüntülerinin değiştirilerek değiştirilmesini istemiyorum. yeni nesneler görüntüleri.

anlaşıldı mı?

Bunu yapmak mümkün mü ve herhangi biri bunu yapmanın iyi bir yolunu önerebilir mi lütfen? GetSubImage'ı düşündüm ancak bir yerde alt görüntüdeki herhangi bir değişikliğin ana görüntüye geri döndüğünü okudum.

Bir BufferedImage'ın tamamen ayrı yeni bir kopyasını veya klonunu elde edebilmek istiyorum.


1
Eğer arayamam clone()yöntemi? Yoksa bir şeyi mi kaçırdım? BufferedImageSınıf hakkında pek bir şey bilmiyorum
Noel M

1
klon yalnızca sığ bir kopya sağlar, böylece ara belleğe alınan görüntülere referansları içerir; kopyaları değil.
Ultimate Gobblement

7
@NoelM, UltimateGobblement: BufferedImageuygulanmaz Cloneableve clone()yöntem korumalı erişime sahiptir.
Robert

Yanıtlar:


173

Bunun gibi bir şey mi?

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
Bunu programımda da ödünç alıyorum =)
Daniel Kats

alt görüntü kopyalamada bu yöntemle ilgili sorun yaşıyorum
mishka

7
Bu çoğu durumda işe yarasa da, BufferedImage kırpıldığında düzgün çalışmaz (kırpılmadan önce tüm görüntüyü döndürür). Bunun basit bir
çözümü

3
yeni BufferedImage (cm, raster, isAlphaPremultiplied, null) .getSubimage (0, 0, bi.getWidth (), bi.getHeight ());
HaydenStudios

copyData (null) her zaman çalışmaz çünkü bir üst raster üzerinde çalışabilir (yani, görüntü bir alt görüntü olduğunda), değiştirilmiş
cevabıma

46

Bunu yapıyorum:

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

Oldukça iyi çalışıyor ve kullanımı basit.


3
Bu oldukça basit görünüyor. Neden bu en iyi cevap değil? Farkında olmadığım bir kusur mu var?
WVrock

2
@WVrock Görüntü türü 0 (özel) ise çalışmaz
Tilman Hausherr

3
Grafikleri değiştirin g = b.getGraphics (); Graphics2D tarafından g = b.createGraphics (); ve mükemmel
Nadir

1
Bunun en temiz cevap olduğunu düşünüyorum. Bununla birlikte, bununla kabul edilen cevap arasında herhangi bir performans farkı var mı? Hayır ise önemsiz gibi hissediyorum. Bu daha hızlı olabilir mi, yalnızca jvm'de nesne oluşturmanın optimize edilmesine neden olabilir. Ayrıca openjdk kullanarak 11. Bu soruyu cevaplayabilecek biri varsa.
thekevshow

18

Alt görüntülere uygulandığında önceden bahsedilen prosedür başarısız olur. İşte daha eksiksiz bir çözüm:

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

Teşekkürler, bir alt görüntüyü klonlamaya çalışırken ofset hatası alıyordum. Bu versiyon tam da ihtiyacım olan şey.
rococo

5

Başka bir yol, Graphics2Dsınıfı yeni bir boş görüntünün üzerine çizmek için kullanmaktır . Bu, görüntüyü gerçekten klonlamaz, ancak üretilen görüntünün bir kopyasıyla sonuçlanır.

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

Bu sorunun oldukça eski olduğunu biliyorum, ancak gelecekteki ziyaretçiler için kullanacağım çözüm şu:

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

Yeni elde edilen newImagegörüntüyü değiştirmek herhangi bir şekilde orijinal görüntüyü de etkiliyorsa lütfen beni düzeltin .
-> Javadoc getScaledInstance için
-> Javadoc SCALE_DEFAULT için (diğer sabitler sadece bu tek aşağıda listelenmiştir)


Bence bu aslında görüntüyü kopyalamayacaktır, yani orijinali değiştirirseniz ölçek de değişecektir, ancak bir süre o kadar kötüydü ki başkası kesin söylemesin.
f1wade

1
Bu aslında görüntüyü kopyalar, çünkü orijinalde yapılan değişiklikler kopyayı değiştirmez. Bu cevap kısa ve özdür ve BufferedImages ile sınırlı bile değildir. Tek sorun, geri dönmesi Imagedeğil BufferedImage.
Kröw
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.