आप एक BufferedImage का क्लोन कैसे बनाते हैं


120

मेरे पास एक ऑब्जेक्ट है जिसमें कई बफ़रडिमेज हैं, मैं एक नई ऑब्जेक्ट बनाना चाहता हूँ जो सभी बफ़रडिमेज को नई ऑब्जेक्ट में कॉपी करता है, लेकिन इन नई छवियों को बदल दिया जा सकता है और मैं नहीं चाहता कि मूल ऑब्जेक्ट की छवियों को बदलकर बदल दिया जाए। नई वस्तुओं छवियों।

स्पष्ट है क्या?

क्या ऐसा करना संभव है और क्या कोई कृपया इसे करने का अच्छा तरीका सुझा सकता है? मैंने getSubImage के बारे में सोचा है, लेकिन कहीं-कहीं पढ़ा है कि सबमेज में कोई भी बदलाव पैरेंट की छवि में वापस आ जाता है।

मैं बस एक पूरी तरह से अलग कॉपी या एक बफ़रेडआईमेज का क्लोन प्राप्त करने में सक्षम होना चाहता हूं


1
क्या आप clone()विधि नहीं कह सकते ? या मुझसे कोई चीज चूक रही है? मैं BufferedImageकक्षा के बारे में बहुत कुछ नहीं जानता
नोएल एम

1
क्लोन केवल एक उथली प्रति प्रदान करता है, इसलिए इसमें बफ़र्ड छवियों के संदर्भ शामिल होंगे; उनकी प्रति नहीं।
अंतिम शोभायात्रा

7
@ नोएलएम, अल्टीमेट गोबलमेंट: BufferedImageलागू नहीं होता है Cloneableऔर इस clone()पद्धति ने संरक्षित पहुंच प्राप्त की है।
रॉबर्ट

जवाबों:


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
मैं अपने कार्यक्रम में यह भी उधार ले रहा हूं =)
डैनियल कैट्स

सबमेज की नकल करने पर इस विधि के साथ समस्या है
mishka

7
हालांकि यह अधिकांश परिस्थितियों में काम करता है, यह ठीक से काम नहीं करता है जब बफ़रमैडम को क्रॉप किया गया है (यह पूरी छवि को क्रॉप करने से पहले वापस कर देता है)। इसके लिए एक सरल समाधान यह है कि अंतिम पंक्ति को इसमें बदल दिया जाए:
हेडेनस्टूडिओस

3
नया बफ़रमैडमेज लौटाएँ (सेमी, रैस्टर, isAlphaPremultiplied, null) .getSubimage (0, 0, bi.getWidth (), bi.getHeight ());
हेडेनस्टूडिओस

copyData (नल) हमेशा काम नहीं करता है क्योंकि यह एक मूल रेखापुंज पर काम कर सकता है (यानी जब छवि एक उप छवि है), मेरा संशोधित जवाब देखें
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

2
@WVrock अगर छवि प्रकार 0 है यह काम नहीं करता है (कस्टम)
टिल्मैन हाशेर

3
ग्राफिक्स g = b.getGraphics () बदलें; Graphics2D g = b.createGraphics () द्वारा; और यह बिल्कुल सही है
नादिर

1
मुझे लगता है कि यह सबसे साफ जवाब है। हालाँकि इस और स्वीकृत उत्तर के बीच कोई प्रदर्शन अंतर है? मुझे नगण्य लगता है अगर कोई नहीं? क्या यह तेजी से विशुद्ध रूप से कारण हो सकता है क्योंकि ऑब्जेक्ट निर्माण jvm में अनुकूलित है। इसके अलावा Openjdk का उपयोग करना 11. यदि कोई भी उस प्रश्न का उत्तर दे सकता है।
थेकेव्सो

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

धन्यवाद, मुझे एक उपखंड में क्लोन करने की कोशिश में एक ऑफसेट त्रुटि मिल रही थी। यह संस्करण बिल्कुल वही है जिसकी मुझे आवश्यकता थी।
रोकोको

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

क्लास बफ़रडैमेज क्लोन करने योग्य इंटरफ़ेस को लागू नहीं करता है। इस प्रकार क्लोन विधि अधिक नहीं है। यहाँ एक गहरी प्रतिलिपि तकनीक के लिए एक विकल्प है: जावा टिप 76: गहरी प्रतिलिपि तकनीक के लिए एक विकल्प


4

मुझे पता है कि यह सवाल बहुत पुराना है, लेकिन भविष्य के आगंतुकों के लिए, यहाँ समाधान मैं उपयोग करूंगा:

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

कृपया मुझे सही करें अगर बस प्राप्त करने को बदलना newImageकिसी भी तरह से मूल छवि को प्रभावित करता है।
-> Javadoc for getScaledInstance
-> SCALE_DEFAULT के लिए Javadoc (अन्य स्थिरांक उसी के नीचे सूचीबद्ध हैं)


मुझे लगता है कि वास्तव में छवि को कॉपी नहीं किया जाएगा, अर्थात यदि आपने मूल स्केल्ड विल्सो को बदल दिया है, लेकिन यह कुछ समय के लिए बीमार है तो किसी और को कहने के लिए सुनिश्चित करें।
f1wade

1
यह वास्तव में छवि की प्रतिलिपि बनाता है, मूल में परिवर्तन कॉपी को नहीं बदलेगा। यह उत्तर संक्षिप्त और संक्षिप्त है और बफ़रडाइम्स तक सीमित नहीं है। एकमात्र मुद्दा यह है कि यह लौटता है Image, नहीं BufferedImage
Kröw
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.