Clipping

Unter Clipping versteht man das Beschneiden einer Grafik am Rand eines vorgegebenen Ausschnittes. Im vorliegenden Beispiel wird ein Hintergrundfoto in eine Schriftkontur eingefügt und das Umfeld einfarbig eingefärbt.

Das Beispiel überschreibt die paint-Methode des abbildenden JLabel. Das Hintergrundbild wird als BufferedImage über die statische Methode read() der Klasse ImageIO geladen. Als Parameter muss ihr ein File-Objekt übergeben werden und der Auslese-Vorgang muss in einen try-catch-Block eingebettet werden, um IOExceptions abzufangen.
Javas Graphics2D-Kontext ist mächtiger als der einfachere und ursprünglichere Graphics-Kontext. Aus diesem Grunde wird der als Parameter der Methode paint(Graphics g) übergebene entsprechend gecastet.
Die anschließend aufgerufenen RenderingHints dienen dem Glätten der in der Folge initialisierten Schrift. Danach beginnt der Code für das eigentliche Clipping.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
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 GlyphDemo {

    String imgName = "src/img/wien.jpg";

    public GlyphDemo() {
        BufferedImage image = null;
        try {
            File file = new File(imgName);
            image = ImageIO.read(file);
        } catch (IOException ex) {
            System.err.println("image '" + imgName + "' couldn't be loaded");
            System.exit(1);
        }
        init(image);
    }

    private void init(BufferedImage image) {
        if (image == null)
            return;
        ImageIcon icon = new ImageIcon(image);
        JLabel label = new JLabel(icon) {
            public void paintComponent(Graphics g) {
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

                // SchriftenVerwenden erzeugen
                Font f = new Font("Verdana", Font.ITALIC | Font.BOLD, 130);

                // Umriss eines Strings als GlyphVector speichern
                GlyphVector gv = f.createGlyphVector(g2d.getFontRenderContext(), "Java");

                // Hintergrund schwarz
                g2d.fill(new Rectangle2D.Float(0, 0, image.getWidth(), image.getHeight()));

                // Clipping Shape von GlyphVector holen
                Shape clipping_shape = gv.getOutline();

                // Clipping Shape soll bei (0,0) beginnen
                g2d.translate(-clipping_shape.getBounds().getX() / 2, -clipping_shape.getBounds().getY() + 150);

                g2d.setClip(clipping_shape);// und setzen

                // das Bild zentriert malen (OHNE Transformation)
                g2d.setTransform(new AffineTransform());

                g2d.drawImage(image, null, 10, 0);
            }
        };
        label.setBorder(new LineBorder(Color.WHITE));

        JPanel panel = new JPanel();
        panel.setLayout(new BorderLayout());
        panel.add(label, BorderLayout.CENTER);
        JFrame frame = new JFrame("Clipping-Frame");
        frame.add(panel);
        frame.setSize(image.getWidth(), image.getHeight());
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

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

Zunächst wird der GlyphVector festgelegt. Hierunter ist die Kontur des vorgegebenen Textes zu verstehen. Er wird auf dem deklarierten Font-Objekt aufgerufen, und bekommt als Parameter den FontRenderContext und den Schriftzug als String übergeben. Darüber wird nun ein (hier) einfarbiges Rechteck gelegt, aus dem schließlich die Kontur mittels GlyphVector.getOutline() ausgeschnitten wird. Es folgen die korrekte Positionierung und das Setzen (=Zeichnen) der Darstellung.
Interessant ist die Zeile g2d.setTransform(new AffineTransform());, deren Notwendigkeit zunächst unklar scheint. Sie verhindert jedoch die Transformation des Grafikkontext. Das Zeichnen des Image-Objektes mit dem Ursprungspunkt in der linken oberen Ecke (0, 0) schließt den Vorgang ab.