2010-02-18 3 views
13

Ich habe Probleme beim Konvertieren eines einfachen PNG in ein JPEG-Format. Ich verwende den folgenden Code:Konvertieren von PNG in JPEG

...

File png = new File(filePath); 
    try { 
     SeekableStream s = new FileSeekableStream(png); 
     PNGDecodeParam pngParams = new PNGDecodeParam(); 
     ImageDecoder dec = ImageCodec.createImageDecoder("png", s, pngParams); 
     RenderedImage pngImage = dec.decodeAsRenderedImage(); 
     JPEGEncodeParam jparam = new JPEGEncodeParam(); 
     jparam.setQuality(0.50f); // e.g. 0.25f 
     File jpeg = new File("jpeg.jpeg"); 
     FileOutputStream out = new FileOutputStream(jpeg); 

     ImageEncoder encoder = ImageCodec.createImageEncoder("JPEG", out, jparam); 

     encoder.encode(pngImage); 

     s.close(); 

    } catch (IOException e) { 
     ok = false; 
     e.printStackTrace(); 
    } 

    return ok; 
} 

...

ich am Ende mit einer JAI Ausnahme up -> java.lang.RuntimeException: Nur 1 oder 3-Band-Byte-Daten können geschrieben werden. bei com.sun.media.jai.codecimpl.JPEGImageEncoder.encode (JPEGImageEncoder.java:148) ...

Keine Optionen mehr. Irgendein Vorschlag?

Antwort

18

Sie wahrscheinlich Alpha-Kanal im png, die Sie benötigen, um loszuwerden, bevor Sie versuchen zu schreibe das jpg.

Erstellen Sie ein neues BufferedImage mit dem Typ TYPE_INT_RGB (nicht TYPE_INT_ARGB) und schreiben Sie dann das Quellbild (pngImage) in das neue leere Bild.

So etwas wie diese (Warnung, nicht getesteten Code):

BufferedImage newImage = new BufferedImage(pngImage.getWidth(), pngImage.getHeight(), BufferedImage.TYPE_INT_RGB); 
newImage.createGraphics().drawImage(pngImage, 0, 0, Color.BLACK, null); 
+0

Elegante Lösung. Es hat perfekt für mich funktioniert. – Norberto

19

Es könnte einfacher sein, ImageIO zu verwenden, um die PNG in eine BufferedImage zu lesen und das Bild im JPEG-Format zu schreiben.

Addendum: Bei diesem Ansatz wird die Konvertierung transparent durch die ImageTranscoder des Verfassers behandelt.

BufferedImage img = ImageIO.read(new File("image.png")); 
ImageIO.write(img, "jpg", new File("image.jpg")); 
+0

Ich denke, Ihre Lösung ist die gleiche wie oben vorgeschlagen. Es funktioniert auch. – Norberto

+1

'ImageIO's Lese-/Schreibkonvertierung ist implizit; Die Konversion in Trevor Harrisons Beispiel ist informativ explizit. – trashgod

+0

+1 ziemlich cool Technik – stacker

3

ich suppse dass JAI das PNG-Bild mit einem indizierten Farbmodell liest und ist nur in der Lage 8-Bit-Graustufen oder 24-Bit-Farbbilder als JPEG-Dateien zu schreiben.

Wenn Sie nicht erforderlich sind für diese Aufgabe JAI zu verwenden, sollten Sie in der Lage sein, ImageIO zu verwenden, anstatt:

ImageIO.write(ImageIO.read(new File("in.png")), "JPEG", new File("out.jpg")); 
+0

Ich habe dies schon einmal versucht und es funktioniert nicht. – Norberto

+0

+1 @Norberto: Können Sie es ausarbeiten? Sieht man genauer hin, ähnelt das dem, was ich vorher benutzt habe. – trashgod

+0

Die obige Implementierung funktioniert nicht wie erwartet. Ich unterstelle nicht, dass das überhaupt nicht funktioniert. In meinem Fall (Bilder, mit denen ich arbeite) funktioniert das nicht. Fehler beim Erstellen der erwarteten Datei und die Ausgabe ist ein falscher Wert. Anscheinend kann es keinen geeigneten Schreiber für das JPEG finden. Ich finde es ziemlich seltsam, aber ich habe keine Zeit zu versuchen, herauszufinden, warum genau es nicht funktioniert. Ich werde in der Zukunft genauer hinsehen, aber um zu wissen, dass ich mich an das halte, was funktioniert. – Norberto

3

Ich fand auch, dass ein PNG-Bild in ein BufferedImage mit ImageIO (Java 6) zu lesen und es heraus zu einem JPG „Formatnamen“ schreiben das Bild wurde beschädigt. Das Bild war da, aber die Farben sahen "solarisiert" und fast umgekehrt aus. Die JPG-Datei war sicher viel kleiner als die PNG-Datei, daher wurde eine Menge Komprimierung durchgeführt. Ich sehe nicht, wie Sie die Komprimierung oder Farbtiefe steuern können.

+0

Ich hatte das gleiche Problem ... ziemlich nervig, schwer zu debuggen. Es ist auf OSX. – jhegedus

1

Ich erhielt die folgende Nachricht in einem etwas anderen Kontext. Die Beseitigung des Alpha-Kanals löste das Problem

javax.imageio.IIOException: Sample size must be <= 8 
    at com.sun.imageio.plugins.jpeg.JPEGImageWriter.write(JPEGImageWriter.java:435) 
    at javax.imageio.ImageWriter.write(ImageWriter.java:580) 
    at com.twelvemonkeys.imageio.plugins.jpeg.JPEGImageWriter.write(Unknown Source) 
    at net.sf.basedb.util.ImageTools.tiffToJpg(ImageTools.java:98) 
    at net.sf.basedb.util.ImageTools.main(ImageTools.java:118)