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.SwingUtilities;
import javax.swing.border.LineBorder;

public class ImageSpeichernClass {

    private final String inStr = "bild_orig.jpg";
    private final String outStr = "bild_save.jpg";
    private final String imgType = "jpeg";
    private final float imgQuality = 0.1f;

    public ImageSpeichernClass() {
        File file = new File(inStr);
        BufferedImage image = loadImg(file);
        if (image == null)
            return;
        initGUI(image);
        saveImg(image, new File(outStr), imgType);
    }

    private void initGUI(BufferedImage image) {
        int imageBreite = image.getWidth();
        int imageHoehe = image.getHeight();

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

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

        JFrame frame = new JFrame("Bild speichern");
        frame.add(panel);
        frame.setSize(imageBreite + 100, imageHoehe + 100);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    private BufferedImage loadImg(File file) {
        BufferedImage image = null;
        try {
            image = ImageIO.read(file);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return image;
    }

    private void saveImg(BufferedImage image, File outFile, String imgType) {
        Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName(imgType);
        ImageWriter writer = (ImageWriter) iter.next();
        ImageWriteParam iwp = writer.getDefaultWriteParam();
        iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        iwp.setCompressionQuality(imgQuality);
        FileImageOutputStream output;
        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();
        }
        writer.dispose();
    }

    public static void main(String args[]) {
        SwingUtilities.invokeLater(() -> new ImageSpeichernClass());
    }
}