2013-02-28 6 views
7

मैं अपने आवेदन में बड़ी छवियों (18000 x 18000) लोड करना चाहता हूं। अगर मैं का उपयोग int_rgb के साथ करता हूं, तो मुझे लोड करने के लिए लगभग 1235 एमबी ढेर मेमोरी की आवश्यकता होती है। यह स्मृति की एक बहुत अधिक मात्रा है, और अंतिम उपयोगकर्ताओं के पास कम रैम (1 जीबी या उससे कम) होगा।मैं BufferedImage के माध्यम से जावा पर एक विशाल छवि कैसे लोड करूं?

मेरे विकास पीसी पर, जब मैं माईक्लिप्स आईडीई से छवि लोड करता हूं, तो यह Exception मेमोरी से बाहर फेंकता है। जब मैं अपने कोड को निष्पादन योग्य जार में पैक करता हूं और इसे अपने पीसी पर एक्लिप्स से बाहर चलाता हूं, तो यह अभी भी एक अपवाद फेंकता है।

1235 एमबी मेमोरी का उपयोग किये बिना buffered छवि का उपयोग करके मैं अपने आवेदन में इतनी बड़ी छवि कैसे लोड करूं? क्या कोई चाल है, छवि को छवि विभाजन जैसे छोटे हिस्सों में विभाजित करना?

मुझे this thread on SO मिला, लेकिन यह मेरे लिए उपयोगी नहीं है; मैं छवि को BufferedImage में लोड करना चाहता हूं और फिर इसे Graphics कक्षा का उपयोग करके Panel पर खींचना चाहता हूं।

उत्तर

6

आप पढ़ सकते हैं और ImageIO पैकेज से ImageReadParam का उपयोग कर छवि के प्रदर्शन के टुकड़े कर सकते हैं।

import java.awt.Image; 
import java.awt.Rectangle; 
import java.awt.image.BufferedImage; 
import java.io.IOException; 
import java.io.InputStream; 
import java.net.URL; 

import javax.imageio.ImageIO; 
import javax.imageio.ImageReadParam; 
import javax.imageio.ImageReader; 
import javax.imageio.stream.ImageInputStream; 
import javax.swing.*; 

public class TestImageChunks { 
    private static void createAndShowUI() { 
     try { 
      URL url = new URL(
        "http://duke.kenai.com/wave/.Midsize/Wave.png.png"); 
      Image chunk = readFragment(url.openStream(), new Rectangle(150, 
        150, 300, 250)); 
      JOptionPane.showMessageDialog(null, new ImageIcon(chunk), "Duke", 
        JOptionPane.INFORMATION_MESSAGE); 
     } catch (IOException e) { 
      JOptionPane.showMessageDialog(null, e.getMessage(), "Failure", 
        JOptionPane.ERROR_MESSAGE); 
      e.printStackTrace(); 
     } 
    } 

    public static BufferedImage readFragment(InputStream stream, Rectangle rect) 
      throws IOException { 
     ImageInputStream imageStream = ImageIO.createImageInputStream(stream); 
     ImageReader reader = ImageIO.getImageReaders(imageStream).next(); 
     ImageReadParam param = reader.getDefaultReadParam(); 

     param.setSourceRegion(rect); 
     reader.setInput(imageStream, true, true); 
     BufferedImage image = reader.read(0, param); 

     reader.dispose(); 
     imageStream.close(); 

     return image; 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
      public void run() { 
       createAndShowUI(); 
      } 
     }); 
    } 
} 

परिणाम इस तरह दिखता है:

enter image description here

+1

आपकी बहुमूल्य टिप्पणियों के लिए धन्यवाद और मैं इसे आज़माउंगा और आपको बता दूंगा। – Mihir

+0

मैंने सफलतापूर्वक आपके समाधान को कार्यान्वित किया और यह काम किया। कृपया, इस मुद्दे पर भी मेरी सहायता करें http://stackoverflow.com/questions/15438506/how-do-i-convert-an-enormous-tiff-image-to-png-jpeg-without-out-of- स्मृति -त्रुटि – Mihir

2

आम तौर पर, अगर आप इस तरह कुछ करने के लिए आवश्यकता होगी:

  • प्रबंधनीय आकार छवि फ़ाइलों में छवि तोड़ और अपने आवेदन के साथ डिस्क पर उन्हें दुकान।
  • इस छवि का एक विशेष भाग प्रदर्शित करते समय, केवल लोड और डिस्प्ले छवि टुकड़े जो आपके व्यूपोर्ट को ओवरलैप करते हैं।
  • जैसे ही आप छवि के चारों ओर पैन करते हैं, लोड और प्रदर्शित छवि टुकड़ों को उचित रूप से अद्यतन करें।
  • या तो अनावश्यक छवि टुकड़े जीसी द्वारा एकत्र किए जाते हैं या नए लोगों को इस तरह से लोड करते हैं कि वे पुराने लोगों को ओवरराइट करते हैं। (हूबहू-आकार की चित्र टुकड़े कि जमा स्मृति बफ़र्स में लोड के लिए यह पिछले तर्क है।)
+0

मैं आपके सिद्धांत से सहमत हूं। वास्तव में मुझे खुशी है कि मैं एक ही दिशा में सोच रहा हूं, लेकिन क्या आप मुझे एक उदाहरण या कोड स्निपेट दे सकते हैं? – Mihir

1

एक पूर्ण समाधान BigBufferedImage है यहाँ एक बुनियादी उदाहरण दिखाता है कि कैसे पूरी छवि पढ़ने के बिना ImageReadParam का उपयोग कर एक भी टुकड़ा पढ़ने के लिए है। यह स्मृति सीमा से अधिक बड़ी छवियों को लोड और स्टोर कर सकता है। चाल यह है कि इसके बफर को डेटाबफर के फ़ाइल आधारित कार्यान्वयन के साथ प्रतिस्थापित किया गया है। यह हार्ड ड्राइव पर छवि स्टोर करता है। कोई राम इस्तेमाल नहीं किया जाता है। यह OutOfMemoryException को रोक सकता है।

एक छवि फ़ाइल से एक BigBufferedImage बनाएँ:

part = image.getSubimage(x, y, width, height); 
0123:

BigBufferedImage image = BigBufferedImage.create(
     tempDir, width, height, TYPE_INT_RGB); 

छवि का हिस्सा प्रस्तुत:

BigBufferedImage image = BigBufferedImage.create(
     inputFile, tempDir, TYPE_INT_RGB); 

एक खाली BigBufferedImage बनाएं

बड़ी छवि हैंडलिंग read this article के बारे में अधिक जानकारी के लिए।

संबंधित मुद्दे