Helligkeit und Kontrast eine Bildes verändern

Status
Nicht offen für weitere Antworten.
B

Beni

Gast
Wie kann man Helligkeit und Kontrast eines Images einfach ändern? Thorsten hat dazu folgende Antwort:

Thorsten hat gesagt.:
Okay... das, was du suchst, ist der LuT :)
LuT == Lookup-Table

Die Helligkeit und der Kontrast hängen beide fest
zusammen über eine simple Geradengleichung
(siehe Mathematik).

Also man kann beide Werte auch ohne LuT ändern,
klar. Nur dauert das viel zu lange. Du musst ja
die Formel für alle Pixel im Bild neu berechnen...

Oder auch nicht. Mit dem LuT hast du für jede
ßnderung nur 255 Berechnungen. Okay, bei
einem kleinen Icon ist das Verfahren vielleicht
schlecht. Aber wenn du ein Foto hast, ist der
Unterschied extrem.

Hier eine Klasse von mir. Die Bezeichnungen
sind der Mathematik nach vergeben.

"a" und "b" sind Steigung und Schnittpunkt
mit der y-Achse.

Unten sieht man die berühmte Formel,
die jeder auswendig können sollte:
y = a * x + b

Java:
public class LUT
{
    private int[] value;
    private double a = 1;
    private double b = 0;
   
    public LUT()
    {
        value = new int[256];
        create();
    }

    public int getLUTValue(int x)
    {
        return value[x];
    }

    public void setA(double a)
    {
        this.a = a;
        create();
    }

    public void setB(double b)
    {
        this.b = b;
        create();
    }

    private void create()
    {
        for (int x = 0; x <= 255; x++)
        {
            value[x] = (int)(a * x + b);
           
            if (value[x] > 255)
            {
                value[x] = 255;
            }
           
            if (value[x] < 0)
            {
                value[x] = 0;
            }
        }
    }
}

Wie gehts weiter? Nun hast du ein Foto in einem
BufferedImage. In einer Schleife liest du nun mit
getRGB() die Werte aus dem Bild. Diesen int-Wert
musst du noch in seine R-, G- und B-Teile aufteilen.

Dazu muss man mit BitShifting arbeiten... auch kein
einfaches Thema. Die Klasse Color von Java kannst
du vergessen, weil du für jeden Pixel eine neue Instanz
erzeugen müsstes *lol*

Also noch ein Geschenk von mir:
Java:
public class RGBColor
{
    private int farbe;
   
    public RGBColor()
    {
    }

    public void setColor(int rgb)
    {
        farbe = rgb;
    }

    public int getRed()
    {
        return (farbe >> 16) & 0xFF;
    }

    public int getGreen()
    {
        return (farbe >> 8) & 0xFF;
    }

    public int getBlue()
    {
        return (farbe >> 0) & 0xFF;
    }

    public void setRGB(int r, int g, int b)
    {
        farbe = ((255 & 0xFF) << 24) | ((r & 0xFF) << 16) | ((g & 0xFF) << 8)  | ((b & 0xFF) << 0);
    }

    public int getRGB()
    {
        return farbe;
    }   
}

Davon eine Instanz erzeugen, und jeden Pixelwert mit setColor()
schreiben. Danach mit getRed, getGreen und getBlue die Anteile
holen.

Für ein Farbbild brauchst du drei LuT. Einen für jeden Farbanteil.


Nochmal eine Zusammenfassung:
  • Beim Programmstart:
  • Eine Instanz von RGBColor anlegen.
  • Drei Instanzen von LUT anlegen.
  • Das Bild muss als BufferedImage vorliegen...
  • ßnderungen am Bild:
  • Mit setA und setB deine Helligkeit und den Kontrast
    einstellen.
  • Dann in einer Schleife alle Pixel aus dem Bild lesen. Immer
    einen nach dem Anderen.
  • Jeden Wert mit setColor() in RGBColor schreiben.
  • Dann die drei Farbanteile lesen.
  • Jeden Farbanteil mit getLUTValue() schreiben. Als Rück-
    gabe erhält man den neuen Wert.
  • Den Rückgabewert von allen drei Farbanteilen mit setRGB()
    in RGBColor schreiben -- du brauchst ja wieder einen int-Wert.
  • Mit getRGB() den Wert lesen, und direkt in das BufferedImage
    mit setRGB schreiben.


Beni hat gesagt.:
Nun ist vielleicht noch die Frage offen: "Wie verwendet man das jetzt?"
Das ist ganz einfach, das Beispiel wird alle Fragen beantworten:
Java:
		BufferedImage image = ... // Ein BufferedImage, welches irgendwo erzeugt wurde.

		LUT lut = new LUT();
		RGBColor color = new RGBColor();

		lut.setA( 0.5 ); // Das LUT mit Werten füllen

		// Jedes Pixel wird angeschaut:
		for( int x = 0, w = image.getWidth(); x<w; x++ ){
			for( int y = 0, h = image.getHeight(); y<h; y++ ){
				 int rgb = image.getRGB( x, y );
				 color.setColor( rgb );

				 // Das hier ist die Transformation
				 color.setRGB( lut.getLUTValue( color.getRed() ),
				 		lut.getLUTValue( color.getGreen() ),
						lut.getLUTValue( color.getBlue() ) );
				 
				 image.setRGB( x, y, color.getRGB() );
			}
		}
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben