RGB-Farbwerte in Bild aufhellen.

Mr.Blue

Neues Mitglied
Der folgende Code wurde uns gegeben, aber wir sollen die jeweiligen Aufgaben nur in der Methode filterRGB() erledigen und den Rest ignorieren.

Java:
import java.awt.*;
import java.awt.image.*;
import java.io.IOException;
import javax.swing.*;

public class PhotoHopp {
    public static void main(String[] args) throws IOException {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Image srcImage1 = toolkit.getImage("river.gif");
        Image srcImage2 = toolkit.getImage("fki_start.jpg");
        Image srcImage3 = toolkit.getImage("farbenkreis_b.gif");


        ImageFilter colorfilter = new TestFilter();
        Image filteredImage1 = toolkit.createImage(
            new FilteredImageSource(srcImage1.getSource(),colorfilter));
        Image filteredImage2 = toolkit.createImage(
            new FilteredImageSource(srcImage2.getSource(),colorfilter));
        Image filteredImage3 = toolkit.createImage(
                new FilteredImageSource(srcImage3.getSource(),colorfilter));
    
        JFrame frame = new JFrame("Images and pixelwise filtering");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setBackground(Color.RED);
        Panel allImagesPanel = new Panel();
        allImagesPanel.setLayout(new GridLayout(0,3));
        allImagesPanel.add(new ImagePanel(srcImage1));
        allImagesPanel.add(new ImagePanel(srcImage2));
        allImagesPanel.add(new ImagePanel(srcImage3));
        allImagesPanel.add(new ImagePanel(filteredImage1));
        allImagesPanel.add(new ImagePanel(filteredImage2));
        allImagesPanel.add(new ImagePanel(filteredImage3));
        frame.getContentPane().add(allImagesPanel);
        frame.setBounds(50,50,1000,500);
        frame.setVisible(true);      
     }
}

class ImagePanel extends JPanel  {
    private Image image;

    public ImagePanel(Image image)  {
        this.image = image;
    }
 
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
//        System.out.println("paintComponent" + this + image.getWidth(this) + " " + image.getHeight(this));
        g.drawImage(image, 10, 10,image.getWidth(this) , image.getHeight(this), this);
    }
}
 
 

class TestFilter extends RGBImageFilter {
 
    public int filterRGB(int x, int y, int pixel) {
       int filteredPixel;
 
       // enjoy working on pixels here
       // extract one color part as an example
       filteredPixel = (pixel & 0xffff0000);
      
       return filteredPixel;
    }
}

Die meisten Aufgaben habe ich hinbekommen, aber mit folgender tue ich mich schwer:

"Helle das Bild auf."

Außer if/else (bzw. ConditionalOP) dürfen wir nichts verwenden, also Schleifen,Arrays etc.

Mein Ansatz sieht so aus:
Java:
int noalpha = pixel & 0x00ffffff;                                    //ohne alpha

int hell = noalpha < 0x00c8c8c8 ? noalpha + 0x00323232 : noalpha;    //wenn noalpha kleiner, dann addieren, wenn nicht, dann keine Veränderung

filteredPixel = (0xff000000)| hell;                                  //wieder mit alpha

return filteredPixel;

Teilweise scheint es zu funktionieren, doch nicht komplett:
SIGbavO


Falls das Bild nicht angezeigt wird: https://imgur.com/bMPfSpA

Zur Not eine Beschreibung:

Eines der Bilder ist ein Farbkreis und nach der Aufhellung sind Blau und Grün schwarz wobei die Ränder der beiden Kreise noch in der Originalfarbe sind. Der rote Kreis und die Schnittmengen mit den anderen beiden Kreisen ist so wie im Original. In den beiden anderen Bildern von Personen oder Gemälden fällt es nicht so sehr auf, aber an wirklich hellen Stellen scheinen die Pixel rot zu werden.

Ich weiß nicht ganz was ich aus diesen Informationen machen soll.

Könnt ihr mir helfen? Wie bekomme ich diese Fehler in den Griff?

Ich bin für jede Hilfe dankbar!
 
Zuletzt bearbeitet:

httpdigest

Top Contributor
Ich bin mir ziemlich sicher, dass du mit einfacher integer-Arithmetik auf dem kodierten RGBA-Wert nicht weit kommen wirst. Dein Vergleich noalpha < 0x00c8c8c8 sieht schonmal seeehr komisch aus. Du _musst_ die R, G, B und A Anteile ersteinmal herausziehen (per Bitoperation) und dann auf diesen Werten einzeln arbeiten.
Da du das Bild "aufhellen" sollst, und in RGB dafür keine direkte Operation existiert (was bedeutet es denn, ein blau "doppelt so hell" zu machen? Ganz sicher nicht einfach den B Kanal mit 2 zu multiplizieren...)
Du benötigst hier andere Farbräume, die extra für solche Sachen erfunden wurden. Schau dir mal den Hue-Saturation-Lightness (HSL) Farbraum an. Dort kannst du direkt die "Helligkeit" einer Farbe beeinflussen. Und es gibt natürlich auch entsprechende Vor- und Rückkonvertierungen von/nach RGB und HSL.
 

Mr.Blue

Neues Mitglied
Vielen Dank! Dann anders:

Mal angenommen ich würde nur den blauen Anteil des Original aufhellen wollen, wäre das möglich ohne den Farbraum zu wechseln?

Ich habe das einfach mal schnell ausprobiert:

Java:
pixelb= (pixel)&(0x000000ff);
pixelg= (pixel>>8)&(0x000000ff);
pixelr= (pixel>>16)&(0x000000ff);

int hellb = pixelb < 0x000000c8 ? pixelb + 0x00000032 : pixelb;

int x = (pixelr << 16)|(pixelg << 8)|(hellb);

filteredPixel = (0xff000000)| x;

return filteredPixel;



Kann ich das mit "< 0x000000c8" besser lösen? Ich möchte erreichen, dass wenn Blau schon maximal ist, er es nicht weiter aufhellt. Ich habe 0xC8 (200) bzw 0x32 (50) genommen, sodass die Aufhellung auch sichtbar ist. Oder habe ich da einen Denkfehler?
 

httpdigest

Top Contributor
Es kommt hier komplett darauf an, was der Aufgabensteller genau unter "aufhellen" versteht.
In meiner Intuition würde die Aussage "Helle das Blau zu x% auf" für ein ausreichend großes 'x' bedeuten: das ganze wird zu weiß.
 

Thallius

Top Contributor
Wie Digest schon schreibt, eine Aufhellung im RGB Farbraum wird immer ein Fusch bleiben, der niemals einwandfrei das gewünschte Ergebnis liefert.

Zu deiner Berechnung:

Warum so kompliziert. In dem Moment wo du die farbwerte einzeln als int vorliegen hast kannst du auch genauso einfach damit rechnen. Also

Blue = Math.min(Blue + Offset, 255);

Gruß

Claus
 

Neue Themen


Oben