Werteüberprüfung und Bildmanipulation mit Hilfe der JAI-Bibliothek1
Die Klasse ermöglicht den Test einiger Einstellungsgrößen von Bildbearbeitungsmethoden der JAI-Bibliothek. Sie lässt sich problemlos um weitere Methoden erweitern.
Über Schieberegler können Werte zur Kontrast- und Helligkeitssteuerung, sowie zur Skalierung ausgelesen und in ihren Auswirkungen überprüft werden.
Zur Erweiterung müssen lediglich in der Methode render() der erforderliche Parameterblock hinzugefügt und der Pfad zum Bild angepasst werden.
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.image.RenderedImage;
import java.awt.image.renderable.ParameterBlock;
import java.io.File;
import java.io.IOException;

import javax.media.jai.JAI;
import javax.media.jai.RenderedOp;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.widget.DisplayJAI;

/*
 * file JAITest.java
 * @version 0.3
 * Created on 23.10.2006
 * Changed on 06.03.2022
 * @author Joerg Czeschla, javabeginners.de (c)2006 - 2022
 */

public class JAITest implements ChangeListener, ActionListener, ItemListener {

    // GUI Elemente
    private JSlider slider1, slider2, slider3;

    private JTextField bildTF, methodeTF, param1TF, param2TF, param3TF;

    private JLabel bildLabel, methodeLabel;

    private JPanel hauptPanel, werteTFPanel, sliderPanel, slider1Panel, slider2Panel, slider3Panel, elementePanel,
            buttonPanel, bildPanel, boxPanel, obenPanel;

    private JButton okButt, cancelButt;

    private JComboBox<String> comboBox;

    private DisplayJAI displayJAI;

    private RenderedImage renderedImage = null;

    // Eingabeverzeichnisname
    private String inputFile = "img/bild.jpg";

    // ComboBox-Starttext
    private String startText = "Bitte Methode w\u00E4hlen!";

    public JAITest() {
        initGUI();
    }

    private void initGUI() {
        // Slider
        slider1 = new JSlider(0, 0, 0);
        slider2 = new JSlider(0, 0, 0);
        slider3 = new JSlider(0, 0, 0);
        slider1.addChangeListener(this);
        slider2.addChangeListener(this);
        slider3.addChangeListener(this);

        // TextFelder
        bildTF = new JTextField(inputFile, 20);
        methodeTF = new JTextField("", 20);
        param1TF = new JTextField("0.00", 5);
        param1TF.addActionListener(this);
        param2TF = new JTextField("75.0", 5);
        param2TF.addActionListener(this);
        param3TF = new JTextField("0.00", 5);
        param3TF.addActionListener(this);

        // Label
        bildLabel = new JLabel("Bild: ");
        methodeLabel = new JLabel("Methode: ");

        // Buttons
        okButt = new JButton("ok");
        okButt.addActionListener(this);
        cancelButt = new JButton("cancel");
        cancelButt.addActionListener(this);

        // ComboBox
        comboBox = new JComboBox<String>();
        comboBox.addItemListener(this);
        comboBox.addItem(startText);
        comboBox.addItem("threshold");
        comboBox.addItem("rescale");
        comboBox.addItem("addConst");
        comboBox.addItem("scale");

        // Panels
        hauptPanel = new JPanel(new BorderLayout());
        werteTFPanel = new JPanel();
        sliderPanel = new JPanel(new BorderLayout());
        slider1Panel = new JPanel(new FlowLayout());
        slider2Panel = new JPanel(new FlowLayout());
        slider3Panel = new JPanel(new FlowLayout());
        bildPanel = new JPanel(new FlowLayout());
        boxPanel = new JPanel(new FlowLayout());
        obenPanel = new JPanel(new BorderLayout());
        elementePanel = new JPanel(new BorderLayout());
        buttonPanel = new JPanel();

        // Bilddisplay
        displayJAI = new DisplayJAI();

        // Slider und Textfelder in Grundstellung setzen
        setAllDisplays(true);

        // Layoutmanagement (der Einfachheit halber ohne GridBagLayout)
        slider1Panel.add(slider1);
        slider1Panel.add(param1TF);
        slider2Panel.add(slider2);
        slider2Panel.add(param2TF);
        slider3Panel.add(slider3);
        slider3Panel.add(param3TF);

        sliderPanel.add(slider1Panel, BorderLayout.NORTH);
        sliderPanel.add(slider2Panel, BorderLayout.CENTER);
        sliderPanel.add(slider3Panel, BorderLayout.SOUTH);

        bildPanel.add(bildLabel);
        bildPanel.add(bildTF);
        boxPanel.add(methodeLabel);
        boxPanel.add(comboBox);
        boxPanel.add(methodeTF);
        obenPanel.add(bildPanel, BorderLayout.NORTH);
        obenPanel.add(boxPanel, BorderLayout.SOUTH);

        buttonPanel.add(okButt);
        buttonPanel.add(cancelButt);

        elementePanel.add(sliderPanel, BorderLayout.NORTH);
        elementePanel.add(werteTFPanel, BorderLayout.CENTER);
        elementePanel.add(buttonPanel, BorderLayout.SOUTH);

        hauptPanel.add(obenPanel, BorderLayout.NORTH);
        hauptPanel.add(elementePanel, BorderLayout.SOUTH);

        // Bild initialisieren
        if (verifyFile(bildTF.getText())) {
            RenderedImage ri = readImg();

            if (ri != null) {
                setzeBild(ri);
            }
        }

        hauptPanel.add(displayJAI, BorderLayout.CENTER);

        JFrame frame = new JFrame("JAI Tool");
        frame.add(hauptPanel);
        frame.setSize(800, 800);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    /**
     * Pr&uuml;ft die Pfadangabe und erzeugt einen InputStream des Bildes
     * 
     * @return FileSeekableStream des zu bearbeitenden Bildes
     */
    private RenderedImage readImg() {
        FileSeekableStream image = null;
        try {
            if (verifyFile(bildTF.getText())) {
                image = new FileSeekableStream(bildTF.getText());
                // RenderedImage erstellen
                renderedImage = JAI.create("stream", image);
                return renderedImage;
            }
        } catch (IOException e) {
            System.out.println("Bitte den Pfad zu einem Bild angeben!");
            setAllDisplays(true);
            return null;
        }
        return null;
    }

    /**
     * Pr&uuml;ft die Pfadangabe auf Existenz und Lesbarkeit
     */
    private boolean verifyFile(String pfad) {
        File f = new File(pfad);
        if (f.isFile() && f.canRead()) {
            return true;
        }
        return false;
    }

    /**
     * positioniert das Bild auf dem Display
     * 
     * @param ri
     * @return
     */
    private void setzeBild(RenderedImage ri) {
        int breite = ri.getWidth(), hoehe = ri.getHeight();
        Dimension dim = new Dimension((800 - breite) / 2, (600 - hoehe) / 2);
        displayJAI.set(ri, (int) dim.getWidth(), (int) dim.getHeight());
    }

    /**
     * Factory-Methode zum methodenabh&auml;ngigen Setzen der Slider
     * 
     * @param slider
     * @param visible sichtbar wenn true
     * @param min     Minimalwert
     * @param max     Maximalwert
     * @param val     Ausgangsposition des Sliders
     */
    private void setSliderValue(JSlider slider, JTextField field, boolean visible, int min, int max, int val) {
        slider.setPreferredSize(new Dimension(300, 25));
        slider.setVisible(visible);
        slider.setMinimum(min);
        slider.setMaximum(max);
        slider.setValue(val);
        field.setVisible(visible);
        field.setText(new Double(val / 100).toString());
    }

    /**
     * Setzt alle Slider und Werte-Textfelder auf Grundstellung
     * 
     * @param visible
     */
    private void setAllDisplays(boolean visible) {
        setSliderValue(slider1, param1TF, visible, 0, 0, 0);
        setSliderValue(slider2, param2TF, visible, 0, 0, 0);
        setSliderValue(slider3, param3TF, visible, 0, 0, 0);
    }

    /**
     * Passt die Werte-Textfelder und Slider-Positionen aneinander an
     * 
     * @param ce
     */
    private void setTFText(ChangeEvent ce) {
        if (ce.getSource() == slider1) {
            param1TF.setText(new Double((double) slider1.getValue() / 100).toString());
        }
        if (ce.getSource() == slider2) {
            param2TF.setText(new Double((double) slider2.getValue() / 100).toString());
        }
        if (ce.getSource() == slider3) {
            param3TF.setText(new Double((double) slider3.getValue() / 100).toString());
        }
    }

    /**
     * Hauptmethode zur Bildbearbeitung
     * 
     * @param im      Zu bearbeitendes RenderedImage
     * @param methode String der anzuwendenden Methode
     * @param wert1   Wert1
     * @param wert2   Wert2
     * @param wert3   Wert3
     */
    private void render(RenderedImage im, String methode, String wert1, String wert2, String wert3) {
        if (renderedImage != null) {
            im = renderedImage;
            System.out.println("renderedImahe ungleich null!");
        }
        System.out.println(methode + " gew\u00E4hlt...");
        ParameterBlock pb = new ParameterBlock();
        pb.addSource(im);
        float f = 1.0F;
        double[] d1 = new double[3];
        double[] d2 = new double[3];
        double[] d3 = new double[3];

        if (methode.equals("") || methode.equals(startText)) {
            return;

        } else if (methode.equals("addConst")) {
            d1[0] = new Double(wert1).doubleValue();
            d1[1] = new Double(wert2).doubleValue();
            d1[2] = new Double(wert3).doubleValue();
            pb.add(d1);

        } else if (methode.equals("rescale")) {
            d1[0] = new Double(wert1).doubleValue();
            d1[1] = new Double(wert1).doubleValue();
            d1[2] = new Double(wert1).doubleValue();
            d2[0] = new Double(wert2).doubleValue();
            d2[1] = new Double(wert2).doubleValue();
            d2[2] = new Double(wert2).doubleValue();
            pb.add(d1);
            pb.add(d2);

        } else if (methode.equals("scale")) {
            f = new Float(wert1).floatValue();

            pb.add(f);
            pb.add(f);
            pb.add(0.0F);
            pb.add(0.0F);
            RenderedOp op = JAI.create(methode, pb);
            int breite = op.getWidth();
            int hoehe = op.getHeight();
            System.out.println("Breite: " + breite);
            System.out.println("Hoehe: " + hoehe);
            System.out.println("Berechnete Breite: " + (displayJAI.getWidth() - breite) / 2.0F);
            System.out.println("Berechnete Hoehe: " + (displayJAI.getHeight() - hoehe) / 2.0F);
            displayJAI.setOrigin((displayJAI.getWidth() - breite) / 2, 0);

        } else {
            d1[0] = new Double(wert1).doubleValue();
            d2[0] = new Double(wert2).doubleValue();
            d3[0] = new Double(wert3).doubleValue();
            if (d1[0] >= d2[0])
                d1[0] = d2[0];
            pb.add(d1);

            if (d2[0] <= d1[0])
                d2[0] = d1[0];
            pb.add(d2);

            pb.add(d3);
        }

        // Bild bearbeiten
        RenderedOp op = JAI.create(methode, pb);
        // bearbeitetes Bild registrieren
        renderedImage = op;
        // Bild darstellen
        displayJAI.set(op);
    }

    /**
     * Aufruf bei Methodenauswahl der Combobox
     */
    public void stateChanged(ChangeEvent ce) {

        setTFText(ce);

        RenderedImage ri = readImg();

        if (ri == null) {
            return;
        }

        render(ri, (String) comboBox.getSelectedItem(), param1TF.getText(), param2TF.getText(), param3TF.getText());
    }

    /**
     * Aufgerufen durch Textfelder und Buttons
     */
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == cancelButt) {
            System.exit(0);
        }
        if (e.getSource() == okButt) {
            RenderedImage ri = readImg();

            if (ri == null) {
                return;
            }
            String methode = (String) comboBox.getSelectedItem();

            render(ri, methode, param1TF.getText(), param2TF.getText(), param3TF.getText());
        }
        if (e.getSource() == param1TF) {
            slider1.setValue((int) (new Double(param1TF.getText()).doubleValue() * 100));
        }
        if (e.getSource() == param2TF) {
            slider2.setValue((int) (new Double(param2TF.getText()).doubleValue() * 100));
        }
        if (e.getSource() == param3TF) {
            slider3.setValue((int) (new Double(param3TF.getText()).doubleValue() * 100));
        }
    }

    /**
     * Sliderwerte je nach Auswahl einer Bearbeitungsmethode setzen und bei Bewegung
     * anpassen
     */
    public void itemStateChanged(ItemEvent e) {
        if (comboBox.getSelectedItem().equals(startText)) {
            setAllDisplays(true);
        }
        if (comboBox.getSelectedItem().equals("rescale")) {
            methodeTF.setText("Kontrast");
            setSliderValue(slider1, param1TF, true, 0, 400, 100);
            setSliderValue(slider2, param2TF, true, -25500, 25500, 0);
            setSliderValue(slider3, param3TF, false, 0, 0, 0);
        }
        if (comboBox.getSelectedItem().equals("threshold")) {
            methodeTF.setText("bin\u00E4rer Kontrast");
            setSliderValue(slider1, param1TF, true, 0, 500, 0);
            setSliderValue(slider2, param2TF, true, 5000, 10000, 7500);
            setSliderValue(slider3, param3TF, true, 0, 10000, 0);
        }
        if (comboBox.getSelectedItem().equals("addConst")) {
            methodeTF.setText("Helligkeit");
            setSliderValue(slider1, param1TF, true, -25000, 25000, 0);
            setSliderValue(slider2, param2TF, true, -25000, 25000, 0);
            setSliderValue(slider3, param3TF, true, -25000, 25000, 0);
        }
        if (comboBox.getSelectedItem().equals("scale")) {
            methodeTF.setText("Skalieren");
            setSliderValue(slider1, param1TF, true, 10, 190, 100);
            setSliderValue(slider2, param2TF, false, 0, 0, 0);
            setSliderValue(slider3, param3TF, false, 0, 0, 0);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() ->  new JAITest());
    }
}
Zur weiteren Vertiefung der JAI-Thematik sei auf die Docs unter

https://docs.oracle.com/cd/E19957-01/806-5413-10/806-5413-10.pdf


verwiesen. Man beachte jedoch, dass diese nicht mehr so ganz aktuell sind. Insbesondere wird auf einige, mittlerweile als deprecated eingestufte Elemente wie etwa ScrollingImagePanel verwiesen. Dies sollte unbedingt durch die Klasse DisplayJAI ersetzt werden.
1)Um die JAI-Bibliothek nutzen zu können, muss diese separat installieren werden.

Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.

letzte Änderung an:
Streams


Javabeginners News-Feed News-Feed abonnieren