2012-11-29 26 views
7

पृष्ठभूमि: मुझे "अक्षम" रूप में इमेजरी बनाने में सक्षम होना चाहिए। आमतौर पर सुझाए गए दृष्टिकोण छवियों को ग्रेस्केल में कनवर्ट करना और ग्रेस्केल छवि दिखाएं। दोष यह है कि यह केवल छवियों के साथ काम करता है, जिससे ग्राफिक्स दिखाने के लिए यह बोझिल हो जाता है जहां आपके पास अक्षम स्थिति में किसी छवि की तत्काल पहुंच नहीं है। अब मैंने सोचा था कि यह java.awt.Composite के साथ फ्लाई पर किया जा सकता है (और फिर मुझे यह जानने की आवश्यकता नहीं होगी कि उदाहरण के लिए कैसे एक आइकन इसे अक्षम करने के लिए लागू किया गया है)। केवल ग्रेस्केल में कनवर्ट करने के लिए कोई कार्यान्वयन नहीं होता है, इसलिए मुझे अपना खुद का निर्माण करना पड़ा ...मैं java.awt.Composite को कुशलतापूर्वक कैसे कार्यान्वित कर सकता हूं?

उस ने कहा, मैंने एक कार्यान्वयन को एक साथ जोड़ दिया है (और यह मुझे इसकी अपेक्षा करता है)। लेकिन मुझे यकीन नहीं है कि यह वास्तव में सभी मामलों के लिए सही ढंग से काम करेगा (समग्र/कंपोजिट कॉन्टेक्स्ट के जावाडॉक्स इस तरह के जटिल ऑपरेशन के लिए बेहद पतले लगते हैं)। और जैसा कि आप मेरे कार्यान्वयन से देख सकते हैं, मैं पिक्सेल द्वारा पिक्सेल को संसाधित करने के लिए एक चौराहे के रास्ते पर जाता हूं, क्योंकि इसमें शामिल रास्टर्स द्वारा निर्धारित प्रारूप में थोक में पिक्सल पढ़ने/लिखने का कोई आसान तरीका नहीं लगता है।

अधिक व्यापक दस्तावेज़ीकरण/उदाहरण/संकेतों के लिए कोई भी संकेतक स्वागत है।

यहां एसएससीसीई है - यह ग्रेडियेंट को ग्रेस्केल में परिवर्तित करने के लिए अक्षम कॉम्पोजिट के माध्यम से एक (रंगीन) ग्रेडियेंटेंट प्रस्तुत करता है। ध्यान दें कि वास्तविक दुनिया में आप नहीं जानते क्या कॉल के साथ प्रस्तुत किया जाता है। ग्रेडियंट वास्तव में केवल एक उदाहरण है (क्षमा करें, लेकिन अक्सर लोग इसे प्राप्त नहीं करते हैं, इसलिए मैं इसे इस बार स्पष्ट कर दूंगा)।

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Composite; 
import java.awt.CompositeContext; 
import java.awt.Dimension; 
import java.awt.GradientPaint; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.RenderingHints; 
import java.awt.image.ColorModel; 
import java.awt.image.Raster; 
import java.awt.image.WritableRaster; 

import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.SwingUtilities; 

public class CompositeSSCE implements Runnable { 

    static class DisabledComposite implements Composite { 
     @Override 
     public CompositeContext createContext(
      final ColorModel srcColorModel, 
      final ColorModel dstColorModel, 
      final RenderingHints hints) { 
      return new DisabledCompositeContext(srcColorModel, dstColorModel); 
     } 
    } 

    static class DisabledCompositeContext implements CompositeContext { 

     private final ColorModel srcCM; 
     private final ColorModel dstCM; 

     final static int PRECBITS = 22; 
     final static int WEIGHT_R = (int) ((1 << PRECBITS) * 0.299); 
     final static int WEIGHT_G = (int) ((1 << PRECBITS) * 0.578); 
     final static int WEIGHT_B = (int) ((1 << PRECBITS) * 0.114); 
     final static int SRCALPHA = (int) ((1 << PRECBITS) * 0.667); 

     DisabledCompositeContext(final ColorModel srcCM, final ColorModel dstCM) { 
      this.srcCM = srcCM; 
      this.dstCM = dstCM; 
     } 

     public void compose(final Raster src, final Raster dstIn, final WritableRaster dstOut) { 
      final int w = Math.min(src.getWidth(), dstIn.getWidth()); 
      final int h = Math.min(src.getHeight(), dstIn.getHeight()); 
      for (int y = 0; y < h; ++y) { 
       for (int x = 0; x < w; ++x) { 
        int rgb1 = srcCM.getRGB(src.getDataElements(x, y, null)); 
        int a1 = ((rgb1 >>> 24) * SRCALPHA) >> PRECBITS; 
        int gray = (
         ((rgb1 >> 16) & 0xFF) * WEIGHT_R + 
         ((rgb1 >> 8) & 0xFF) * WEIGHT_G + 
         ((rgb1  ) & 0xFF) * WEIGHT_B 
         ) >> PRECBITS; 
        int rgb2 = dstCM.getRGB(dstIn.getDataElements(x, y, null)); 
        int a2 = rgb2 >>> 24; 
        int r2 = (rgb2 >> 16) & 0xFF; 
        int g2 = (rgb2 >> 8) & 0xFF; 
        int b2 = (rgb2  ) & 0xFF; 
        // mix the two pixels 
        gray = gray * a1/255; 
        final int ta = a2 * (255 - a1); 
        r2 = gray + (r2 * ta/(255*255)); 
        g2 = gray + (g2 * ta/(255*255)); 
        b2 = gray + (b2 * ta/(255*255)); 
        a2 = a1 + (ta/255); 
        rgb2 = (a2 << 24) | (r2 << 16) | (g2 << 8) | b2; 
        Object data = dstCM.getDataElements(rgb2, null); 
        dstOut.setDataElements(x, y, data); 
       } 
      } 
     } 

     @Override 
     public void dispose() { 
      // nothing for this implementation 
     } 
    } 

    // from here on out its only the fluff to make this a runnable example 
    public static void main(String[] argv) { 
     Runnable r = new CompositeSSCE(); 
     SwingUtilities.invokeLater(r); 
    } 

    // simple component to use composite to render 
    static class DemoComponent extends JComponent { 
     // demonstrate rendering an icon in grayscale with the composite 
     protected void paintComponent(Graphics g) { 
      Graphics2D g2d = (Graphics2D) g; 
      GradientPaint p = new GradientPaint(0, 0, Color.GREEN, 127, 127, Color.BLUE, true); 
      g2d.setComposite(new DisabledComposite()); 
      g2d.setPaint(p); 
      g2d.fillRect(0, 0, getWidth(), getHeight()); 
     } 
    } 

    // Fluff to use the Composite in Swing 
    public void run() { 
     try { 
      JFrame f = new JFrame("Test grayscale composite"); 
      DemoComponent c = new DemoComponent(); 
      c.setPreferredSize(new Dimension(500, 300)); 
      f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
      f.setLayout(new BorderLayout()); 
      f.add(c, BorderLayout.CENTER); 
      f.pack(); 
      f.setVisible(true); 
     } catch (Exception e) { 
      throw new RuntimeException(e); 
     } 
    } 

} 

उत्तर

3

तुम हमेशा एक BufferedImage बना सकते हैं, जो कुछ भी आकर्षित ग्रे बढ़ाया कि छवि bufferedImage.createGraphics() प्रयोग करने के लिए Graphics वस्तु के लिए होने की जरूरत है, और फिर javax.swing.GreyFilter का उपयोग छवि का एक ग्रे बढ़ाया प्रतिलिपि बनाने के लिए।

This page shows you how to use a Filter

आप स्विंगएक्स के BlendComposite के साथ अपने दृष्टिकोण की तुलना भी करना चाहेंगे, जो मुझे उम्मीद है कि आप वही काम करते हैं जो आप कर रहे हैं। BlendComposite में एक संतृप्ति मोड है जो ग्रे-स्केल की अनुमति देगा। मैं उम्मीद उनके बीच कोई महत्वपूर्ण अंतर है, मध्यवर्ती कदम उठाए है, क्योंकि, और (यह भी अधिक मोड हैं।)

This page has a demo of BlendComposite.

दक्षता के बारे में, से मैं क्या देख सकते हैं, दोनों के साथ छवि डेटा का पूरा प्रतियां। लेकिन यदि आपने सुझाई गई पहली विधि का उपयोग करके भूरे रंग की छवि को बनाए रखा है, तो आप गैर-गतिशील नियंत्रणों के पुनर्मूल्यांकन को रोक सकते हैं।

यदि आप उपर्युक्त में से कोई एक करते हैं, तो प्रदर्शन सही होगा, और मुझे उम्मीद है कि आप वास्तव में यही चाहते हैं।

आपकी टिप्पणियों से मुझे लगता है कि आप केवल एक घटक पर प्रभाव लागू करना चाहते हैं। इसके लिए आप JLayer का उपयोग कर सकते हैं, केवल जावा 7 में उपलब्ध है। Javadoc से पारदर्शी हरे रंग को ओवरले करने का एक उदाहरण है। आप इसे भूरे रंग से बदल सकते हैं। यदि आप जावा के पिछले संस्करणों में जेएलएयर का उपयोग करना चाहते हैं तो आप स्विंगएक्स प्रोजेक्ट का हिस्सा JXLayer का उपयोग कर सकते हैं।

+0

ब्लेंडकंपोसाइट एक उपयोगी टूल की तरह दिखता है, संकेत के लिए धन्यवाद। हालांकि एक त्वरित नज़र से ऐसा लगता है कि हर संभव रंगमोडल के साथ इसकी रचना() - विधि में काम नहीं करता है, शायद अन्य रंग मॉडल अभ्यास में प्रासंगिक नहीं हैं? "आप हमेशा एक बुफर्ड इमेज बना सकते हैं" के रूप में, मैं नहीं देखता कि मैं इसे कैसे बना सकता हूं() - विधि कार्यान्वयन। इसे पेंट कॉम्पोनेंट() में कहीं भी करना संभव होगा, लेकिन यह समग्र सेट करने की तुलना में बहुत कम लचीला है और फिर सामान्य प्रतिपादन श्रृंखला के साथ आगे बढ़ें। – Durandal

+0

@ डुरंडल मुझे नहीं पता कि यह सभी रंग मॉडल के लिए उपयुक्त है (और मुझे नहीं पता कि इस संदर्भ में रंगमोडेल का क्या उपयोग किया जाता है, हालांकि मैं अनुमान लगा सकता हूं), जो मुझे पता है, और जिस कारण से मैंने सुझाव दिया है, स्विंगएक्स ने आधिकारिक स्विंग टीम से इनपुट किया है, इसलिए इसे सामान्य उपयोगों के लिए लचीला होना चाहिए। मेरे पहले सुझाव के साथ, आप कंपोजिट का उपयोग नहीं करेंगे, और मैं इसे पेंट कॉम्पोनेंट में करूँगा - यह उतना ही लचीला है, बस अधिक काम (ड्राइंग आकार में छवि बनाएं, इसे खींचें, इसे फ़िल्टर करें, इसे पेंट करें; और कैश आकार का उपयोग करने के लिए आखिरी वाला उपयोग करें) .... – Tom

+0

@ डुरंडल आप BufferedImage के लिए 'ग्राफिक्स' बना सकते हैं और उसके बाद उस ग्राफिक्स उदाहरण के साथ 'paintComponent' को कॉल कर सकते हैं। – Tom

0

मुझे खेद है कि अगर मैं आपके प्रश्न को सही तरीके से समझ नहीं पा रहा हूं लेकिन maybe this आपकी मदद करेगा? यह एक छवि ग्रेस्केल बनाने के लिए सीएसएस का उपयोग करता है।

भी this क्या आप देख रहे हैं? यह छवियों में हेरफेर करने के लिए jquery और कैनवास का उपयोग करता है।

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

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