Wie kann man auf die einzelnen Pixel eines Bildes zugreifen und diese manipulieren?

Das Beispiel stellt zwei Methoden bereit, die zeigen wie man ohne Verwendung von Filtern auf die Bildpunkte eines vorhandenen Bildes Einfluss nehmen und wie man auf ähnliche Weise ein Bild völlig neu erstellen kann.

Die Methode processImage() liest zunächst über die statische Methode ImageIO.read(File file) ein Bild als BufferedImage über dessen File-Objekt ein. Das zugehörige ColorModel und Raster werden ermittelt. Die Klasse ColorModel kapselt Methoden zur Konvertierung der Pixelwerte in Farb- und Transparenzkomponenten und deren Bearbeitung. Ein Raster repräsentiert ein Array, das die Pixelwerte eines definierten rechteckigen Bereiches beschreibt.
In einer geschachtelten Schleife werden die einzelnen Pixel mittels getDataElements() ausgelesen und deren RGB-Wert als int über das Model ermittelt. Hiermit kann nun ein Color-Objekt erstellt werden, dessen einzelne Farb-Komponenten ausgelesen und beliebig manipuliert werden können. Im Beispiel wird jeder Farbwert dann um 50 erhöht, wenn nach Addieren von limit der Grenzwert von 255 nicht überschritten wird. Da sich hierdurch die Anzahl rein weißer Pixel erhöht, kommt es zur Bildung weißer Flächen im Bild.
Der Rest der Methode kehrt den Prozess des Auslesens um: ein neues Color-Objekt wird gebildet, ein entsprechender int-Wert erstellt, der ins ColorModel eingelesen und auf's Raster gesetzt wird.

package grafik.bildbearbeitung;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.WritableRaster;
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.border.LineBorder;

public class ManipulateImage extends JFrame {

    private static final long serialVersionUID = 1L;

    JPanel panel;

    JLabel label;

    ImageIcon icon;

    BufferedImage image;

    public ManipulateImage() {

        //processImage();
        makeImage();
        
        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(image.getWidth() + 100, image.getHeight() + 100);
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
    }
    
    private void processImage(){
        File file = new File("test.jpg");
        try {
            this.image = ImageIO.read(file);
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        
        ColorModel model = image.getColorModel();
        
        WritableRaster raster = image.getRaster();
        for(int i=0; i<image.getWidth(); i++){
            for(int j=0; j<image.getHeight(); j++){
                
                Object dataAlt = raster.getDataElements(i, j, null);
                int argbAlt = model.getRGB(dataAlt);
                
                Color c = new Color(argbAlt, true);
                
                int limit = 150, wert = 50;
                
                int r = (c.getRed() + limit) < 256 ? c.getRed() + wert : 255;
                int g = (c.getGreen() + limit) < 256 ? c.getGreen() + wert : 255;
                int b = (c.getBlue() + limit) < 256 ? c.getBlue() + wert : 255;
                
                Color cNeu = new Color(r, g, b);
                
                int argbNeu = cNeu.getRGB();
                
                Object dataNeu = model.getDataElements(argbNeu, null);
                
                raster.setDataElements(i, j, dataNeu);
            }
        }
    }
    
    private void makeImage(){
        int width = 200, height = 200;
        image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        WritableRaster raster = image.getRaster();
        ColorModel model = image.getColorModel();
        
        Color c1 = Color.RED;
        int argb1 = c1.getRGB();
        Object data1 = model.getDataElements(argb1, null);
        
        Color c2 = Color.GRAY;
        int argb2 = c2.getRGB();
        Object data2 = model.getDataElements(argb2, null);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                raster.setDataElements(i, j, data1);
                if(i>50 && i<150 && j>50 && j<150){
                    raster.setDataElements(i, j, data2);
                }
            }
        }
    }

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

Das Verfahren von makeImage() ist prinzipiell gleich. Es wird jedoch ein leeres, beliebig grosses (hier 200 x 200 px) BufferedImage-Objekt erstellt, Raster und ColorModel werden ermittelt und zwei Color-Objekte gebildet. Nach Wandel und Auslesen der Data-Arrays mittels getDataElements() werden die Pixelwerte in einer geschachtelten Schleife dem Raster übergeben.

Das Ergebnis sieht wie folgt aus.

Ergebnis von makeImage()