2012-01-06 14 views
6

मैं अपारपी का उपयोग करके बुद्धब्रोट फ्रैक्टल जेनरेटर लिख रहा हूं। मुझे इसका ओपनसीएल हिस्सा काम करने के लिए मिला, जिसके परिणामस्वरूप एक एकल-आयाम सरणी है जो प्रत्येक पिक्सेल का प्रतिनिधित्व करती है। मेरे पास अंतिम इमेज के रूप में अंतिम छवि के आयाम हैं, और उस सरणी में मनमानी बिंदुओं के सूचकांक प्राप्त करने के लिए कोड लिखा है। मैं इसे एक छवि के रूप में सहेजना चाहता हूं और मैं BufferedImage का उपयोग TYPE_USHORT_GRAY के साथ करने का प्रयास कर रहा हूं। यहां मेरे पास अब तक है:संक्षिप्त [] को एक ग्रेस्केल छवि में बदलें

BufferedImage image=new BufferedImage(VERTICAL_PIXELS, HORIZONTAL_PIXELS, BufferedImage.TYPE_USHORT_GRAY); 
    for(int i=0; i<VERTICAL_PIXELS; i++) 
     for(int k=0; k<HORIZONTAL_PIXELS; k++) 
      image.setRGB(k, i, normalized[getArrayIndex(k,i,HORIZONTAL_PIXELS)]); 

समस्या यह है कि, मुझे नहीं पता कि आरजीबी को किस प्रकार सेट करना है। मुझे क्या करना चाहिये?

उत्तर

7

समस्या यह है कि setRGB() एक 0xRRGGBB रंग मान चाहता है। BufferedImage नाटक करना पसंद करता है कि छवि आरजीबी है, कोई फर्क नहीं पड़ता कि डेटा के रूप में क्या संग्रहीत किया जाता है। आप वास्तव में आंतरिक DataBufferShort (getTile(0, 0).getDataBuffer() के साथ) पर प्राप्त कर सकते हैं, लेकिन यह पता लगाना मुश्किल हो सकता है कि यह कैसे निर्धारित किया जाता है।

int[] buffer = /* pixels */; 

ColorModel model = new ComponentColorModel(
    ColorSpace.getInstance(ColorSpace.CS_GRAY), new int[] { 16 }, 
    false, true, Transparency.OPAQUE, DataBuffer.TYPE_USHORT); 

Image image = Toolkit.getDefaultToolkit().createImage(
    new MemoryImageSource(VERTICAL_PIXELS, HORIZONTAL_PIXELS, 
         model, buffer, 0, VERTICAL_PIXELS)); 

इस दृष्टिकोण का लाभ यह है कि आप को नियंत्रित कि:

आप पहले से ही एक short[] में अपने पिक्सल है, एक सरल समाधान के लिए उन्हें एक MemoryImageSource में बजाय एक int[] एक यह जाम में कॉपी करने के लिए हो सकता है अंतर्निहित पिक्सेल सरणी। आप उस सरणी में परिवर्तन कर सकते हैं और पर newPixels() पर कॉल कर सकते हैं, और यह लाइव अपडेट होगा। यह भी आप ग्रेस्केल से अपनी खुद की अन्य पैलेट परिभाषित करने के लिए पूरा शक्ति देता है:

int[] cmap = new int[65536]; 
for(int i = 0; i < 65536; ++i) { 

    cmap[i] = (((i % 10000) * 256/10000) << 16) 
      | (((i % 20000) * 256/20000) << 8) 
      | (((i % 40000) * 256/40000) << 0); 
} 
ColorModel model = new IndexColorModel(16, 65536, cmap, 0, false, -1, DataBuffer.TYPE_USHORT); 

यह दृष्टिकोण ठीक काम करता है अगर आप सिर्फ स्क्रीन पर छवि प्रदर्शित करना चाहते हैं:

JFrame frame = new JFrame(); 
frame.getContentPane().add(new JLabel(new ImageIcon(image))); 
frame.pack(); 
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
frame.setVisible(true); 

हालांकि, अगर आप चाहते थे इसे फ़ाइल में लिखने के लिए और एक-शॉर्ट-प्रति-पिक्सेल प्रारूप (कहें, मैटलैब में लोड करने के लिए) को सुरक्षित रखें, फिर आप भाग्य से बाहर हैं। सबसे अच्छा आप इसे BufferedImage में पेंट करना और ImageIO से सहेजना है, जो आरजीबी के रूप में सहेज जाएगा।

आप निश्चित रूप से अंत में एक BufferedImage की जरूरत है, एक और दृष्टिकोण, रंग अपने आप को पैलेट लागू आरजीबी मूल्यों की गणना करने के लिए है, और फिर उन्हें छवि में कॉपी:

short[] data = /* your data */; 
int[] cmap = /* as above */; 
int[] rgb = new int[data.length]; 

for(int i = i; i < rgb.length; ++i) { 
    rgb[i] = cmap[data[i]]; 
} 

BufferedImage image = new BufferedImage(
    VERTICAL_PIXELS, HORIZONTAL_PIXELS, 
    BufferedImage.TYPE_INT_RGB); 

image.setRGB(0, 0, VERTICAL_PIXELS, HORIZONTAL_PIXELS, 
    pixels, 0, VERTICAL_PIXELS); 
+0

मैंने किया है कि, तो एहसास हुआ कि मेरी ड्राइंग कोड हर जगह ArrayOutOfBounds अपवादों के साथ FUBAR है। इसे देखकर, ऐसा लगता है कि यह ठीक काम करेगा। मुझे बस इतना करना है कि इसे एक .png के रूप में आउटपुट करें, जिसे मैंने सफलतापूर्वक किया है (उम्मीद है)। मैं इसे सही के रूप में चिह्नित करूंगा क्योंकि ऐसा लगता है कि यह ठीक काम करेगा। –

+0

जब यह छवि में पिक्सेल डालता है, तो क्या यह उन्हें लंबवत रेखाओं में खींचता है जो बाईं ओर से शुरू होता है और शीर्ष पर शुरू होता है और नीचे जाता है? क्योंकि मेरे आंशिक रूप से काम करने वाले कोड में छवि 90 डिग्री घड़ी की दिशा में घूमती है और मुझे नहीं लगता कि यह ड्राइंग की गलती है। –

+0

कभी नहीं!मुझे मेमोरी इमेजसोर्स भाग में 200 को HORIZONTAL_PIXELS में बदलना पड़ा। यह बहुत अच्छा काम करता है, धन्यवाद! –

3

संदर्भ के लिए, इस उदाहरण से पता चलता है कैसे दो अलग BufferedImage प्रकार एक ही 16 बिट डेटा की व्याख्या करते हैं। आप पिक्सल मान देखने के लिए छवियों पर माउस कर सकते हैं।

परिशिष्ट: शब्द व्याख्या पर विस्तार से बता दें ध्यान दें कि setRGB() की कोशिश करता दिया ColorModel में निर्दिष्ट मान के लिए निकटतम मैच खोजने के लिए।

BufferedImageTest

import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.GridLayout; 
import java.awt.Point; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.image.BufferedImage; 
import java.util.Random; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

/** @see http://stackoverflow.com/questions/8765004 */ 
public class BufferedImageTest extends JPanel { 

    private static final int SIZE = 256; 
    private static final Random r = new Random(); 
    private final BufferedImage image; 

    public BufferedImageTest(int type) { 
     image = new BufferedImage(SIZE, SIZE, type); 
     this.setPreferredSize(new Dimension(SIZE, SIZE)); 
     for (int row = 0; row < SIZE; row++) { 
      for (int col = 0; col < SIZE; col++) { 
       image.setRGB(col, row, 0xff00 << 16 | row << 8 | col); 
      } 
     } 
     this.addMouseMotionListener(new MouseAdapter() { 

      @Override 
      public void mouseMoved(MouseEvent e) { 
       Point p = e.getPoint(); 
       int x = p.x * SIZE/getWidth(); 
       int y = p.y * SIZE/getHeight(); 
       int c = image.getRGB(x, y); 
       setToolTipText(x + "," + y + ": " 
        + String.format("%08X", c)); 
      } 
     }); 
    } 

    @Override 
    protected void paintComponent(Graphics g) { 
     g.drawImage(image, 0, 0, getWidth(), getHeight(), null); 
    } 

    static private void display() { 
     JFrame f = new JFrame("BufferedImageTest"); 
     f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     f.setLayout(new GridLayout(1, 0)); 
     f.add(new BufferedImageTest(BufferedImage.TYPE_INT_ARGB)); 
     f.add(new BufferedImageTest(BufferedImage.TYPE_USHORT_GRAY)); 
     f.pack(); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       display(); 
      } 
     }); 
    } 
} 
+1

तकनीकी रूप से बोलते हुए, ये वही 16 बिट डेटा नहीं दिखा रहे हैं - वे एक ही आरजीबी मूल्य दिखा रहे हैं जब यूएसएचओआर ग्रेस्केल या आरजीबी में प्रवेश किया जाता है। ऐसा इसलिए है क्योंकि setRGB() छवि के पैलेट में रंग रूपांतरण करता है - यह केवल पिक्सेल मान नहीं लिखता है। यदि यह पिक्सेल मान लिखा है, तो ग्रेस्केल नीचे सफेद होगा। –

+0

+1। कार्य उदाहरण + छवियों के साथ प्रतिक्रियाएं अच्छी हैं – Robin

+0

@RussellZahniser सही है; ऊपर से अधिक – trashgod

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