# Grafikanzeige ausgrauen



## s.schmidt (20. Jun 2008)

Hallo,

ich habe eine recht aufwändig erstellte farbige Grafikausgabe (Graphics g) in Java. Gibt es einen einfachen Weg, die Anzeige z.B. vorrübergehend auszugrauen (in Graustufen darzustellen), ohne das der Code, welcher die Grafik erzeugte, vorher dafür ausgelegt wurde.

gibt es da Möglichkeiten oder Ideen?

danke
sebastian


----------



## Marco13 (21. Jun 2008)

Einfach und sinnvoll wohl nicht. Man könnte bei paintComponent in das Graphics eines BufferedImages malen, das nur Graustufen darstellt, und dieses BufferedImage dann über die eigentliche Component drüberpinseln. Man könnte es aber auch sein lassen.


----------



## Wildcard (21. Jun 2008)

Marco13 hat gesagt.:
			
		

> Man könnte es aber auch sein lassen.


 :lol: 
Wenn du einen eigenen Parent um die Komponenten legen kannst, kannst du das Graphics Objekt das du durchreichst in einen Wrapper packen.
Der Wrapper überschreibt Graphics#setForeground und setBackground und verändert die Farbwerte.
Oder man lässt es einfach sein...


----------



## Krondor (23. Jun 2008)

Vielleicht könnte man auch einfach ein transparentes Viereck über die gesamte Ausgabe zeichnen 

Wie macht man das? So!
http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html#Java2D-Tutorial-Transparency


----------



## Quaxli (23. Jun 2008)

Krondor hat gesagt.:
			
		

> Vielleicht könnte man auch einfach ein transparentes Viereck über die gesamte Ausgabe zeichnen
> 
> Wie macht man das? So!
> http://www.apl.jhu.edu/~hall/java/Java2D-Tutorial.html#Java2D-Tutorial-Transparency



Könnte man.....  Aber die Farbe ändert sich nicht wirklich. Wie man das rausfindet? So: 


```
import javax.swing.*;
import java.awt.*;


public class Demo extends JPanel {

	public static void main(String[]args){
		new Demo();
	}
	
	public Demo(){
		JFrame frame = new JFrame("demo");
		frame.setLocation(100,100);
		frame.setSize(200,200);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(this);
		frame.setVisible(true);
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		Graphics2D g2 = (Graphics2D)g;
		
		g2.setColor(Color.RED);
		g2.fillRect(20,20,50,50);

		g2.setColor(Color.GREEN);
		g2.fillRect(100,100,50,50);
		
		g2.setColor(Color.GRAY);
		g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f)); 
		g2.fillRect(0,0,getWidth(),getHeight());
		g2.dispose();
	}

}
```


----------



## Illuvatar (23. Jun 2008)

Vielleicht könnte man aber mit einem selbst geschrieben Composite schon auch "richtig" ausgrauen. Bin ich aber grade überfragt wie man das genau machen würde.


----------



## Krondor (23. Jun 2008)

> Könnte man..... Aber die Farbe ändert sich nicht wirklich.



hmmm.... jup.
War auch nur so nen Gedanke. Kommt jetzt halt drauf an wofür er das Ausgrauen benutzen möchte. Wenn er wirklich aus den Farben aus irgendeinem Grund unbedingt Grautöne machen möchte ist das Ganze natürlich nix. Wenn er aber dem Benutzer nur darstellen möchte, dass seine grafische Oberfläche nicht mehr nutzbar ist o.ä. genügt es ihm vielleicht.


----------



## Quaxli (23. Jun 2008)

Ich hab' mal die Idee von Marco aufgegriffen: Funktioniert soweit, nur der Hintergrund wird etwas anders dargestellt, wenn man den aber standardmäßig mit fillRect(...) eine eigene Farbe gibt, paßt das auch eingermaßen.
Beim Beispiel unten habe ich mal die beiden Möglichkeiten mit transparentem "Filter" und grauem Image getestet. Je nachdem, wie man den boolean setzt, wird anders "gegraut". 



```
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;


public class Demo extends JPanel {

	boolean gray = true;
	
	public static void main(String[]args){
		new Demo();
	}
	
	public Demo(){
		JFrame frame = new JFrame("demo");
		frame.setLocation(100,100);
		frame.setSize(200,200);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.add(this);
		frame.setVisible(true);
	}

	@Override
	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		
		Graphics2D g2;
		BufferedImage img = null;
		
		if(!gray){
			g2 = (Graphics2D)g;

			g2.setColor(Color.blue);
			g2.fillRect(0,0,getWidth(),getHeight());
			
			g2.setColor(Color.RED);
			g2.fillRect(20,20,50,50);

			g2.setColor(Color.GREEN);
			g2.fillRect(100,100,50,50);
			
			g2.setColor(Color.GRAY);
			g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5f)); 
			g2.fillRect(0,0,getWidth(),getHeight());
		}else{
			img = new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_BYTE_GRAY);
			g2 = img.createGraphics();
			
			g2.setColor(Color.blue);
			g2.fillRect(0,0,getWidth(),getHeight());
			
			g2.setColor(Color.RED);
			g2.fillRect(20,20,50,50);

			g2.setColor(Color.GREEN);
			g2.fillRect(100,100,50,50);
			
			g.drawImage(img, 0, 0, this);

		}

		g2.dispose();
		
	}

}
```


----------



## Krondor (23. Jun 2008)

Schöne Variante


----------



## Illuvatar (23. Jun 2008)

So, meine Methode funktioniert übrigens auch. Obwohl es nicht ganz der eigentliche Verwendungszweck von Composites ist, finde ich es schöner als mit einem BufferedImage.

Trotzdem würde ich das BufferedImage vorziehen, denn das folgende ist nicht sehr ausgereift. Der Code verlässt sich darauf, dass (so wie es bei mir beim Testen immer war) src einen Alpha-Kanal besitzt und dstOut keinen. Außerdem ist es langsam, da müsste man noch mit dem Profiler ran 


```
import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.color.ColorSpace;


public class Demo extends JPanel {

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

   public Demo(){
      JFrame frame = new JFrame("demo");
      frame.setLocation(100,100);
      frame.setSize(200,200);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.add(this);
      frame.setVisible(true);
   }

   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);

      Graphics2D g2;

      g2 = (Graphics2D)g;
      g2.setComposite(new TestComposite());

      g2.setColor(Color.BLUE);
      g2.fillRect(0,0,getWidth(),getHeight());

      g2.setColor(Color.RED);
      g2.fillRect(20,20,50,50);

      g2.setColor(Color.GREEN);
      g2.fillRect(100,100,50,50);

      g2.setColor(Color.WHITE);
      g2.drawString("Ich bin Weiß", 20, 100);

      g2.dispose();

   }

}

class TestComposite implements Composite, CompositeContext {
  private ColorSpace graySpace = ColorSpace.getInstance(ColorSpace.CS_GRAY);

  public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints) {
    return this;
  }

  public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {

    assert src.getNumBands() == 4;
    assert dstOut.getNumBands() == 3;
  
    Rectangle bounds = src.getBounds();
    int[] pixels = src.getPixels(bounds.x, bounds.y, bounds.width, bounds.height, (int[])null);
    int numPx = pixels.length / 4;
    int[] pxOut = new int[numPx * 3];
    
    float[] rgb = new float[3];
    for (int i = 0; i < numPx; i++) {
      rgb[0] = pixels[i*4] / 255f; // immer vier Werte aus pixels[] bilden ein RGBA-Pixel
      rgb[1] = pixels[i*4 + 1] / 255f;
      rgb[2] = pixels[i*4 + 2] / 255f;
      float[] gray = graySpace.fromRGB(rgb);
      pxOut[i*3] = pxOut[i*3 + 1] = pxOut[i*3 + 2] = (int)Math.round(255 * gray[0]); // immer drei Werte in pxOut bilden ein RGB-Pixel
    }

    bounds = dstOut.getBounds();
    dstOut.setPixels(bounds.x, bounds.y, bounds.width, bounds.height, pxOut);
  }

  public void dispose() {
  }
}
```


----------

