Wie lässt sich der Farbraum eines Bildes ermitteln?

Gelegentlich kann es von Bedeutung sein, beim Umgang mit Bilddateien deren Farbraum zu ermitteln, z.B. weil ImageIO nicht ohne Weiteres mit dem im Druckbereich gängigen CMYK-Farbraum zurecht kommt. Mit Hilfe der JAI-Bibliothek und der Reflection-API kann man sich diesem Problem nähern. Ein zweistufiges Annähern liefert zunächst den Wert einer Variablen, die den gefundenen Farbraum repräsentiert und dann den Variablennamen.

Um das u.a. Beispiel ausführen zu können, muss neben dem Anpassen des Pfades zur Bilddatei noch die JAI-Bibliothek in den Klassenpfad eingebunden werden.

Ermitteln des Farbraumes als Variablenwert

Im Beispiel wird innerhalb von main() die Methode getColorSpaceFromImg() aufgerufen, die einen Pfad zu einer Bilddatei als Parameter übergeben bekommt. Mit diesem wird zunächst ein File -Objekt erzeugt, das durch einen SeekableStream gekapselt wird. Die Klasse FileSeekableStream ist Teil der JAI-Bibliothek, die zum fortgeschrittenen Image-Processing unter Java verwendet wird.
Das so erzeugte RenderedOp -Objekt stellt eine Methode getAsBufferedImage() bereit, die ein BufferedImage als Ausgangspunkt der Untersuchung liefert.
Um Ein- und Ausgabefehler abzufangen, muss diese Operation in einem try-catch -Block ausgeführt werden.

import java.awt.color.ColorSpace;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;

import javax.media.jai.JAI;

import com.sun.media.jai.codec.FileSeekableStream;
import com.sun.media.jai.codec.SeekableStream;

public class DetectColorSpace {

    public static void main(String[] args) {
         getColorSpaceFromImg("CMYK_img.jpg");
    }

    private static void getColorSpaceFromImg(String path) {
        File file = new File(path);
        BufferedImage img = null;
        SeekableStream seekableStream = null;
        try {
            seekableStream = new FileSeekableStream(file);
            img = JAI.create("Stream", seekableStream).getAsBufferedImage();
        } catch (IOException e) {
            e.printStackTrace();
        }

        int type = img.getColorModel().getColorSpace().getType();

        // determining the human readable name of the color space variable
        Class<ColorSpace> cs = ColorSpace.class;
        Field[] fields = cs.getDeclaredFields();

        for (Field f : fields) {
            try {
                int fieldValue = (int) f.get(null);
                if (fieldValue == type)
                    System.out.println("Farbraum: " + f.getName()
                            + ", Variablenwert: " + fieldValue);
            } catch (IllegalArgumentException | IllegalAccessException e) {
            }
        }
    }
}

Das Auslesen des Farbraumes geschieht in einer 3-stufigen Methoden-Kaskade, während der zunächst das Farb-Modell, dann das zugehörige Farbraum-Objekt und schließlich dessen Typ ermittelt wird. Dieser wird als int -Wert geliefert, der in der Klasse ColorSpace als final static Variable, also als eine Art Konstante, deklariert ist. Hiermit ist das Auslesen des Farbraumes selbst bereits abgeschlossen.

Auslesen des Variablen-Bezeichners des gefundenen Variablen-Wertes

Die Werte dieser Farbraum-Variablen sind unter Namen abgelegt, die zumindest näherungsweise den Namen des jeweiligen Farbraumes wiedergeben. Um nicht jedes Mal nachschlagen zu müssen, können diese mit Hilfe der Reflection-API ermittelt werden.
Hierzu wird zunächst das Class -Objekt der Klasse ColorSpace erzeugt. Dessen Methode getDeclaredFields() liefert ein Array aller Klassen- und Instanzvariablen, das in der Folge in einer for -Schleife durchlaufen wird.
In jedem Durchlauf wird der Wert jeder einzelnen Variablen ermittelt und mit dem oben aus der Bilddatei ausgelesenen Wert verglichen. Sind beide identisch, so wird über die Methode getName() des Field -Objektes der Bezeichner der Variablen ausgelesen und ausgegeben. Um Fehlzugriffe abzufangen, müssen auch diese Operationen durch einen try-catch -Block abgesichert werden.