2008-11-05 13 views
8

मैं java.awt.image.BufferedImage से एक पीएनजी फ़ाइल लिखने की कोशिश कर रहा हूं। सब कुछ ठीक काम करता है लेकिन परिणामस्वरूप पीएनजी एक 32-बिट फ़ाइल है।जावा में, आप एक java.awt.image.BufferedImage को 8-बिट पीएनजी फ़ाइल में कैसे लिखते हैं?

क्या पीएनजी फ़ाइल 8-बिट बनाने का कोई तरीका है? छवि ग्रेस्केल है, लेकिन मुझे पारदर्शिता की आवश्यकता है क्योंकि यह एक ओवरले छवि है। मैं जावा 6 का उपयोग कर रहा हूं, और मैं आउटपुटस्ट्रीम वापस करना पसंद करूंगा ताकि मैं कॉलिंग क्लास को डिस्क/डीबी में फ़ाइल लिखने के साथ सौदा कर सकूं।

यहाँ कोड के संबंधित भाग है:

public static ByteArrayOutputStream createImage(InputStream originalStream) 
      throws IOException { 

     ByteArrayOutputStream oStream = null; 

     java.awt.Image newImg = javax.imageio.ImageIO.read(originalStream); 
     int imgWidth = newImg.getWidth(null); 
     int imgHeight = newImg.getHeight(null); 
     java.awt.image.BufferedImage bim = new java.awt.image.BufferedImage(imgWidth, 
       imgHeight, java.awt.image.BufferedImage.TYPE_INT_ARGB); 

     Color bckgrndColor = new Color(0x80, 0x80, 0x80); 

     Graphics2D gf = (Graphics2D)bim.getGraphics(); 

     // set transparency for fill image 
     gf.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f)); 
     gf.setColor(bckgrndColor); 
     gf.fillRect(0, 0, imgWidth, imgHeight); 

     oStream = new ByteArrayOutputStream(); 
     javax.imageio.ImageIO.write(bim, "png", oStream); 
     oStream.close(); 

     return oStream; 
    } 
+0

अधिक जानकारी हो सकती है http://stackoverflow.com/questions/665406/make-a-color-transparent-in-bufferedimage-to-be-saved-as-png – VonC

उत्तर

1

यह एक दिलचस्प सवाल यह है कि ... यह देर हो चुकी है, मैं कल प्रयोग करेंगे। मैं पहली बार एक BufferedImage.TYPE_BYTE_INDEXED (शायद ड्राइंग के बाद) का उपयोग करने के लिए कोशिश करूंगा कि यह देखने के लिए कि जावा 8 बिट पीएनजी उत्पन्न करने के लिए पर्याप्त स्मार्ट है या नहीं।
या शायद कुछ छवि लाइब्रेरी इसे अनुमति दे सकती है।

[संपादित करें] कुछ साल बाद ... वास्तव में, मैंने उस समय कोड बनाया, लेकिन इस धागे को अपडेट करना भूल गया ... मैंने the code pointed at by Kat का उपयोग किया, पारदर्शिता के संचालन पर थोड़ा परिष्करण, और पीएनजी में बचत जीआईएफ प्रारूप के बजाय प्रारूप। यह सभी-या-कुछ पारदर्शिता के साथ 8-बिट पीएनजी फ़ाइल बनाने में काम करता है।

आप http://bazaar.launchpad.net/~philho/+junk/Java/view/head:/Tests/src/org/philhosoft/tests/image/AddTransparency.java पर मेरी ImageUtil कक्षा का उपयोग कर एक कार्यरत परीक्षण फ़ाइल पा सकते हैं।

चूंकि कोड इतना बड़ा नहीं है, पोस्टरिटी के लिए, मैं इसे कुछ लाइनों को सहेजने के लिए जावाडोक के बिना यहां पोस्ट करता हूं।

public class ImageUtil 
{ 
    public static int ALPHA_BIT_MASK = 0xFF000000; 

    public static BufferedImage imageToBufferedImage(Image image, int width, int height) 
    { 
    return imageToBufferedImage(image, width, height, BufferedImage.TYPE_INT_ARGB); 
    } 

    public static BufferedImage imageToBufferedImage(Image image, int width, int height, int type) 
    { 
    BufferedImage dest = new BufferedImage(width, height, type); 
    Graphics2D g2 = dest.createGraphics(); 
    g2.drawImage(image, 0, 0, null); 
    g2.dispose(); 
    return dest; 
    } 

    public static BufferedImage convertRGBAToIndexed(BufferedImage srcImage) 
    { 
    // Create a non-transparent palletized image 
    Image flattenedImage = transformTransparencyToMagenta(srcImage); 
    BufferedImage flatImage = imageToBufferedImage(flattenedImage, 
     srcImage.getWidth(), srcImage.getHeight(), BufferedImage.TYPE_BYTE_INDEXED); 
    BufferedImage destImage = makeColorTransparent(flatImage, 0, 0); 
    return destImage; 
    } 

    private static Image transformTransparencyToMagenta(BufferedImage image) 
    { 
    ImageFilter filter = new RGBImageFilter() 
    { 
     @Override 
     public final int filterRGB(int x, int y, int rgb) 
     { 
     int pixelValue = 0; 
     int opacity = (rgb & ALPHA_BIT_MASK) >>> 24; 
     if (opacity < 128) 
     { 
      // Quite transparent: replace color with transparent magenta 
      // (traditional color for binary transparency) 
      pixelValue = 0x00FF00FF; 
     } 
     else 
     { 
      // Quite opaque: get pure color 
      pixelValue = (rgb & 0xFFFFFF) | ALPHA_BIT_MASK; 
     } 
     return pixelValue; 
     } 
    }; 

    ImageProducer ip = new FilteredImageSource(image.getSource(), filter); 
     return Toolkit.getDefaultToolkit().createImage(ip); 
    } 

    public static BufferedImage makeColorTransparent(BufferedImage image, int x, int y) 
    { 
    ColorModel cm = image.getColorModel(); 
    if (!(cm instanceof IndexColorModel)) 
     return image; // No transparency added as we don't have an indexed image 

    IndexColorModel originalICM = (IndexColorModel) cm; 
    WritableRaster raster = image.getRaster(); 
    int colorIndex = raster.getSample(x, y, 0); // colorIndex is an offset in the palette of the ICM' 
    // Number of indexed colors 
    int size = originalICM.getMapSize(); 
    byte[] reds = new byte[size]; 
    byte[] greens = new byte[size]; 
    byte[] blues = new byte[size]; 
    originalICM.getReds(reds); 
    originalICM.getGreens(greens); 
    originalICM.getBlues(blues); 
    IndexColorModel newICM = new IndexColorModel(8, size, reds, greens, blues, colorIndex); 
    return new BufferedImage(newICM, raster, image.isAlphaPremultiplied(), null); 
    } 
} 
+0

4 साल बाद, अभी भी एक और सवाल के बजाय उत्तर देने का इंतजार कर रहा है। – mjaggard

+1

मुझे मेरी प्रतिक्रिया पर कोई प्रश्न नहीं दिख रहा है, हालांकि ईमानदारी से मुझे कोई जवाब नहीं दिख रहा है (हे, मैं उस समय एसओ पर नया था ...)। वैसे भी, स्वर के बावजूद, सिर के लिए धन्यवाद। – PhiLho

+0

स्वर के लिए खेद है, इसे आक्रामक लगाना नहीं था। इसलिए आपको यह निर्दिष्ट करने के लिए कहा जाता है कि आप नीचे मतदान क्यों कर रहे हैं, इसलिए मैं उस प्रश्न का उत्तर दे रहा था। – mjaggard

4

ImageIO png लेखक सभी प्लेटफार्मों मैं इस पर इस्तेमाल किया है, कोई बात नहीं क्या स्रोत छवि है पर 32 बिट PNG फ़ाइलें लिखेंगे में निर्माण। आपको यह भी पता होना चाहिए कि कई लोगों ने शिकायत की है कि परिणामस्वरूप संपीड़न पीएनजी प्रारूप के साथ संभव है उससे काफी कम है। कई स्वतंत्र png libraries उपलब्ध हैं जो आपको सटीक प्रारूप निर्दिष्ट करने की अनुमति देते हैं, लेकिन मुझे वास्तव में उनमें से किसी के साथ कोई अनुभव नहीं है।

0

प्रतिक्रिया देने के लिए धन्यवाद, मैं इंडेक्सकोलर मॉडल के साथ TYPE_BYTE_INDEXED को आजमाने की कोशिश कर रहा था और फिर भी यदि छवि छवि 32-बिट लिखती है तो ऐसा लगता है कि मैं अपना समय बर्बाद कर सकता हूं।

जिस छवि को मैं लिखने की कोशिश कर रहा हूं वह बहुत बड़ा हो सकता है (8000x4000 तक) लेकिन नीचे छवि के लिए सिर्फ एक साधारण मुखौटा है, इसलिए केवल ~ 30% पारदर्शी ग्रे और 100% पारदर्शी कटआउट होगा। मैं एक जीआईएफ का उपयोग करता हूं लेकिन आईई 6 में बड़ी संख्या में प्रदर्शित होने में परेशानी होती है।

यह केवल एक बार और एक आंतरिक सेट-अप प्रकार स्क्रीन में उत्पन्न होता है, इसलिए प्रदर्शन कोई मुद्दा नहीं है, लेकिन इसे जावा कोड के भीतर किया जाना चाहिए, न कि ऑफलाइन उपयोगिता द्वारा।

आपके द्वारा निर्दिष्ट पुस्तकालयों को लिखते समय इसे बदलने के लिए उपयोग किया जा सकता है ... मैं इसे जांचने जा रहा हूं।

यदि किसी के पास बेहतर तरीका है, तो कृपया मुझे बताएं !!

धन्यवाद!

1

मैं कैसे यहाँ इंडेक्स को RGBA कन्वर्ट करने के लिए के रूप में जवाब मिला: http://www.eichberger.de/2007/07/transparent-gifs-in-java.html

हालांकि, जिसके परिणामस्वरूप 8 बिट PNG फ़ाइल केवल 100% या 0% पारदर्शिता है।आप शायद इंडेक्सकोलरोडेल सरणी को ट्विक कर सकते हैं, लेकिन हमने जेनरेट की गई फ़ाइल (ओवरले मास्क क्या था) को अंडरले जेपीजी में बनाने का निर्णय लिया है और पारदर्शी ओवरले के रूप में स्थिर आधार का उपयोग किया है।

+1

अपनी पोस्ट के उत्तरों पर ध्यान देने के बजाय, आप वास्तव में संपादन पर क्लिक करके अपने मूल प्रश्न में जानकारी जोड़ सकते हैं। उपयोगकर्ता देख सकते हैं कि क्या बदला गया है और यह केवल उत्तर कॉलम पर जोड़ना नहीं रखता है। –

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