Wie kann ein *.jpg in einer definierten Qualität gespeichert werden?

Die Klassen IOImage und IIOImage eröffnen die Möglichkeiten, ein *.jpg-Bild in einer definierten Qualität zu komprimieren und zu speichern.

Das Beispiel liest zunächst eine *.jpg-Datei ein und stellt das Bild im Original auf einem JLabel dar. Über die Methode getImageWritersByFormatName() der Klasse ImageIO wird dann ein Iterator-Objekt erzeugt, das alle systemeigenen Writer-Objekte listet, die die Codierung im angegebenen Format vornehmen können. Hieraus wird mittels next() das erste ermittelt. Auf dem Writer-Objekt wird ein ImageWriteParam -Objekt erzeugt und für das Speichern von typzugehörigen Parameterwerten vorbereitet ( ImageWriteParam.MODE_EXPLICIT ). JPG erlaubt diesbezüglich die Festlegung der Kompressionsqualität, die der Methode setCompressionQuality() als Float-Wert zwischen 0 und 1 übergeben wird (0 niedrige, 1 hohe Qualität). Zu Demonstrationszwecken verwendet das Beispiel eine extrem starke Kompression mit dem Ergebnis entsprechend schlechter Bildqualität. Zum Speichern wird ein FileOutputStream erzeugt, der als Parameter das File-Objekt der neu zu speichernden Datei erhält. Die Klasse IIOImage stellt einen Container bereit, in dem neben einer Bilddatei als RenderedImage eine List mit Thumbnails und Metadaten gespeichert werden können. Die letzten beiden Parameter sind im Beispiel leer. Der ImageWriter schreibt die Daten schließlich in den Stream.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.stream.FileImageOutputStream;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;

public class ImageSpeichernClass extends JFrame {

    private static final long serialVersionUID = 1L;

    JPanel panel;

    JLabel label;

    ImageIcon icon;

    BufferedImage image = null;

    public ImageSpeichernClass() {

        File file = new File("img/test.jpg");

        try {
            this.image = ImageIO.read(file);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        int imageBreite = image.getWidth();
        int imageHoehe = image.getHeight();

        icon = new ImageIcon(image);
        label = new JLabel(icon);
        label.setBorder(new LineBorder(Color.WHITE));

        panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.setBackground(Color.DARK_GRAY);
        panel.add(label, BorderLayout.CENTER);

        getContentPane().add(panel);
        setSize(imageBreite + 100, imageHoehe + 100);

        Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpeg");
        ImageWriter writer = (ImageWriter)iter.next();
        ImageWriteParam iwp = writer.getDefaultWriteParam();
        iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        iwp.setCompressionQuality(0.1f);
        File outFile = new File("img/test1.jpg");
        FileImageOutputStream output = null;
        try {
            output = new FileImageOutputStream(outFile);
            writer.setOutput(output);
            IIOImage img = new IIOImage((RenderedImage) image, null, null);
            writer.write(null, img, iwp);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(output != null) output.close();
            } catch (IOException ioe) {}
        }
        writer.dispose();

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
        setVisible(true);
    }

    public static void main(String args[]) {
        new ImageSpeichernClass();
    }
}