# Farblayer berechnen



## Clip (23. Apr 2007)

Hallo,

ich möchte über ein Bild einen Farblayer legen. Natrülich programmatisch, sonst würe ich auch in einem Photoshopforum fragen 
Das ganze passiert in SWT. Das ist aber eigentlich egal, denn meine Frage ist SEHR grundsätzlicher Natur. Ich kann bereits auf jeden Pixel einer Grafik zugreifen, nur auch auch dessen rot, grüen und blau Wert richtig auszulesen funktioniert noch nciht so gut ...Am besten erstmal der bestehende Code:

```
private void colorize() {
		ImageData ideaImageData = imageDesciptor.getImageData();
		
		// Die Layer Farbwerte (alles sollte ersteinmal beimalten bleiben)
		int redShift = 0;
		int greenShift = 0;
		int blueShift = 0;

		int[] lineData = new int[ideaImageData.width];
		for (int y = 0; y < ideaImageData.height; y++) {
			ideaImageData.getPixels(0, y, ideaImageData.width, lineData, 0);
			// Analyze each pixel value in the line
			for (int x = 0; x < lineData.length; x++) {
				// Extract the red, green and blue component
				int pixelValue = lineData[x];				
				int r = pixelValue & redShift;
				int g = (pixelValue & greenShift) >> 8;
				int b = (pixelValue & blueShift) >> 16;
				// weiß oder fast weiß auf ganz weiß setzen ;)
				if (r > 230 && g > 230 && b > 150) {
					ideaImageData.setPixel(x, y, 0xFFFFFF);
				} else {
//  ------------>                  hier soll der neue Wert hin
					ideaImageData.setPixel(x, y, ???);
				}
			}
		}
		// SWT ImageDescriptor erstellen
		Image image = new Image(null, ideaImageData);
		imageDesciptor = ImageDescriptor.createFromImage(image);
	}
```
Das Problem ist, dass der neu Berechnete Wert immer schwarz ist. (Ausser die Farbe ist fast oder ganz weiß, siehe Code)
Ich muss also wissen, wie ich einen Farbwert richtig auslesen , und im Anschluss den neu berechneten wieder einfügen kann.

Weiß jemand wie das geht?
Danke


----------



## The_S (24. Apr 2007)

http://www.java-forum.org/de/viewtopic.php?t=46880&highlight=rgb


----------



## Clip (24. Apr 2007)

Danke, es funktionier (fast) mit dem unteren Code. Leider geht das setzten der Farbe aber noch nicht s.u.
Code:
	
	
	
	





```
for (int x = 0; x < lineData.length; x++) {
				// Extract the red, green and blue component
				int pixelValue = lineData[x];
				int r = (pixelValue >> 16) & 0xFF; 
				int g = (pixelValue  >> 8) & 0xFF; 
				int b = (pixelValue >> 0) & 0xFF; 
				//System.out.println(r + " " + g + " " + b);
				ideaImageData.setPixel(x, y, (((((b) >> 8) & g) >> 16) & r));
			}
```
Damit erhalte ich inwischen jeden Farbwert richtig. Zum Test möchte ich jetzt den Pixelfarbwert wieder aus r, g und b zusamensetzten um so das Bild in den originalen Farbwerten zu erhalten. Wenn das funktioniert, kann ich anfnagen die Farbwerte zu verändern. Leider funktioniert es aber noch nicht so ganz. Mit der '!tollen' (von mir anscheinend sinnfrei) ausgedachten Mehtode den Wert zu berechnen '(((((b) >> 8) & g) >> 16) & r)'  bekomme ich aufjedenfall immer nur ein schwarz.... Da ich in Sachen bitweises und/oder noch ein Neuling bin habe ich nicht so den rechten Plan wie ich aus den drei Werten wieder einen Farbwert berechnen kann. 
Weiß jemand wie das geht?
Danke!


----------



## The_S (24. Apr 2007)

```
rgb = ((a & 0xFF) << 24) |
               ((r & 0xFF) << 16) |
               ((g & 0xFF) << 8)  |
               ((b & 0xFF) << 0);
```


----------



## Clip (24. Apr 2007)

Super Danke!

Also mit SWT und ImageDesciptor s geht das so:

```
public ImageDescriptor getColoredImageDescriptor() {
		
		Color maskColor = new Color(null, 219, 249,185);
		
		imageDesciptor = IconProvider.getImageDescriptor(image, imageSize);
		ImageData ideaImageData = imageDesciptor.getImageData();
		
		int mask_r = maskColor.getRed();
		int mask_g = maskColor.getGreen();
		int mask_b = maskColor.getBlue();


		int[] lineData = new int[ideaImageData.width];
		for (int y = 0; y < ideaImageData.height; y++) {
			ideaImageData.getPixels(0, y, ideaImageData.width, lineData, 0);
			// Analyze each pixel value in the line
			for (int x = 0; x < lineData.length; x++) {
				// Extract the red, green and blue component
				int pixelValue = lineData[x];
				//System.out.println("alt " + pixelValue);
				int r = (pixelValue >> 16) & 0xFF; 
				int g = (pixelValue  >> 8) & 0xFF; 
				int b = (pixelValue >> 0) & 0xFF; 
				
				// Neuer Farbwerte mit der Maske überlagern
				r = (r & mask_r);
				g = (g & mask_g);
				b = (b & mask_b);
				
				// neuen Farbwert berechnen
				int neu = ((r & 0xFF) << 16) 
							| ((g & 0xFF) << 8)  
							|((b & 0xFF) << 0);				
								
				//System.out.println("neu " + neu);
				ideaImageData.setPixel(x, y, neu);
			}
		}
		;
		maskColor.dispose();
		Image image = new Image(null, ideaImageData);
		imageDesciptor = ImageDescriptor.createFromImage(image);
		return imageDesciptor;
	}
```


----------



## Leroy42 (24. Apr 2007)

Clip hat gesagt.:
			
		

> Natrülich programmatisch



Wer ist eigentlich schuld, das dieses Wort immer
wieder falsch benutzt wird.

Wenn überhaupt dann heißt es programm_technisch_  :meld:


----------



## Clip (24. Apr 2007)

Ich habe noch eine Frage. Wofür ist der Wert a in 
	
	
	
	





```
((a & 0xFF) << 24)
```
 ??


----------



## The_S (24. Apr 2007)

alpha


----------



## Clip (24. Apr 2007)

Hm wofür bracht man denn das? (Sorry bin in Sachen Grafik nicht so bewandert).

Ich habe noch ein Problem beim addieren von Farbwerten. Nach dem ich mal mit exotischeren Farben getestet habe als (255,0,0), habe ich bemerkt, dass sich einige neu berechnete Farben recht eigenwillig verhalten. Teilweise "rutschen" sie krass in einen anderen Farbwert ab. Ich weiß auch nicht so genau wie ich das erklären soll 

Ist an der Vorgehensweise:
	
	
	
	





```
r = (r & mask_r);
				g = (g & mask_g);
				b = (b & mask_b);
```
 etwas nicht vollständig oder falsch?


----------



## The_S (24. Apr 2007)

1.) alpha = transparenz
2.) welche Werte haben den die jeweiligen "Masken"? Was möchtest du damit erreichen?


----------



## Clip (24. Apr 2007)

Es geht um folgende Anwendgung. Ich habe beliebige Icons als PNGs in meiner Anwendung. In Listen, Bäumen und Tabellen werden Daten durch diese Icons repräsentiert. Die Daten haben bestimmte Merkmale. Der Anwender soll beliebigen Merkmalen beliebige Farben zuordnen können. Aus diesem Grund möchte ich die vom Benutzer ausgewählten Farben auf die Icons anwenden. Dazu habe ich mir ein leicht graues, fast weisse Icon mit 3D Efeckt erstellt, und wende je nach Datenmerkmalen die vom Benuter definierten Farben auf das Icon an. Bildlich gesprochen genau das was passiert wennich mir eine farbige Sonnenbrille auf die Nase setzte 
Alles funktioniert, nur leider werden die Farben bei bestimmten zu addierenden Farbwerten etwas komisch dargetsellt.... :autsch:


----------



## The_S (24. Apr 2007)

Und warum wurstelst du dann mit nem AND-Vergleich in der Gegend rum?

Nur ein Beispiel:

00011101 = 1 + 4 + 8 + 16 = 29
00000111 = 1 + 2 + 4 = 7

00011101 & 00000111 = 00000101 = 1 + 4 = 5
29 + 7 = 36


----------



## Clip (24. Apr 2007)

Weil ich nicht weiss wie sonst gehen soll...
Addiere ich das ganze einfach, sehen die Farbverläufe zwar wieder gut aus, allerdings haben die Farben überhaupt nichts mehr mit denen zu tun die ich haben will (ping, rosa, orange etc).


----------



## The_S (25. Apr 2007)

kommt halt darauf an wie genau der user die farbe einstellen kann. Wenn er 3 Slider hat für r, g und b, dann musst du halt daraus jeweils die neue Farbe berechnen, auch wenns scheiße aussieht. Muss du schon selber wissen, wie der User Farben manipulieren kann, und wie sich das Ganze dann auf dein Bild auswirkt


----------



## Clip (25. Apr 2007)

Ja, der User hat son ein typischen Farbdialog. Ob scheisse aussieht oder nicht ist mir egal. Das muss der User schon selber wissen. Mein Problem ist aktuell eher, dass ich die Farben nicht richtig berechne. Ich kenne keinen Algorythmus wie das zuverlässig zu bewerkstelligen wäre.


----------



## The_S (25. Apr 2007)

tja und ich weiß nicht, WIE die Farben berechnet werden sollen. Also was du gegeben hast, wie sie verändert werden sollen, ...


----------



## Clip (25. Apr 2007)

Was ich berechnen möchte ist sozusagen ein "Sonnenbrillen" Efeckt. Also eine Farbe (z.B. 72, 215, 130 (ein Grünton)) flächendeckend über ein Grafik legen. Dabei soll die Grafik natürlich noch zu erkennen sein. Ich möchte also einen vorhandenen Pixel so berechnen, dass die Pixelfarbe und die Layerfarbe eine neue Farbe ergeben die entsprechend der physikalischen Gesetzte die 'richtige' ist.


----------



## The_S (25. Apr 2007)

Spontan:

Du errechnest den Mittelwert aller 3 Farbkanäle eines Pixels. Somit kannste schonmal graustufen. Jetzt erhöhst bzw. verringerst du die Werte jedes Farbkanals relativ zu deiner gegebenen Wunschfarbe. Fertig.


----------



## Clip (25. Apr 2007)

Der Mittelwert scheint zu reichen:

```
int pixelValue = lineData[x];
				int r = (pixelValue >> 16) & 0xFF;
				int g = (pixelValue >> 8) & 0xFF;
				int b = (pixelValue >> 0) & 0xFF;

				// Neuer Farbwerte mit der Maske überlagern (Mittelwert)							
				r = (r + mask_r) / 2;
				g = (g + mask_g) / 2;
				b = (b + mask_b) / 2;
				// neuen Farbwert berechnen
				int neu = ((r & 0xFF) << 16) | ((g & 0xFF) << 8)
						| ((b & 0xFF) << 0);
```

Vielen Dank!!!!!


----------



## The_S (25. Apr 2007)

Thread abhaken nicht vergessen


----------



## Clip (25. Apr 2007)

Jetzt weiss ich was du mit "jetzt kannst du schon mal grau" meinst 
Die von mir berechneten Farben sehen alle zwar eingefärbt, aber dennoch leicht grau aus.

Das mit dem relativen Verschieben des Farbwertes, wie von Dir geschrieben ,ist anscheinent für den letzten Pfif entscheident.

Aber wie kann ich den Wert verschieben? Angenommen ich will Rot und Blau vermischen.

Mit meinr Formel:
r(255) + r(0) / 2 = r(128)
g(0) + g(0) / 2 = g(0)
b(0) + b(255) = b(128)

Herauskommt ein dunkles Lila.

Eigentlich müsste es aber ein knall Lila (255,0,255) sein.

Was ich machen könnte, wäre auf den neu berechneten Wert noch mal den Layerfarbwert zu addieren, maximal jedoch bis 255. Allerdings, das ist reine Spekulation...


```
r = r + mask_r < 255 ? r + mask_r : 255;
	            g = g + mask_g < 255 ? g + mask_g : 255;
	            b = b + mask_b < 255 ? b + mask_b : 255;
```

Das Ergebnis sind deutlich knalligere Farben. Sie erscheinen eigentlich schon übertrieben...
Leider werde ich im Internet in Sachen korrekten Berechnung nich so recht fündig..


----------



## The_S (26. Apr 2007)

Nene, so hab ich das eigentlich auch gemeint  . Wenn du nunmal einen Ausgangswert von 0, 0, 0 also schwarz hast, dann kannste net erwarten, dass dabei leuchtende Farben rauskommen. Ich bin jetzt davon ausgegangen, dass du wirklich nur ein normales pic mit einer Farbe in verschiedenen hell- und dunkeltönen haben möchtest (die Variante mit dem mittel-Wert). Möchtest du aber die Originalfarben weitesgehend erhalten, dann addiere einfach den Originalfarbkanal mit dem entsprechenden der gewünschten Farbe und teile das Ergebnis dann durch 2. So haste du so nen "Ich schimmer in der und der Farbe, hab aber dennoch die Originalfarben"-Effekt  .

Eine weitere Alternative wäre, über das Bild einfach ein (zu einem bestimmten Anteil transparentes) Rechteck zu zeichnen. So kannst du die intensität deines "Sonnenbrillen-Effekts" sehr gut selbst regulieren.


```
BufferedImage img = new BufferedImage(src.getWidth(), src.getHeight(), BufferedImage.TYPE_INT_ARGB);
		Graphics2D g = img.createGraphics();
		g.drawImage(src, 0, 0, null);
		g.setColor(new Color(col.getRed(), col.getGreen(), col.getBlue(), 100));
		g.fillRect(0, 0, img.getWidth(), img.getHeight());
		g.dispose();
```

Aber vorsicht, ein Image mit transparenz, kann auch nur in ein Grafikformat, das Transparenz unterstützt gespeichert werden (z. B. .png).


----------



## Clip (26. Apr 2007)

Woher weißt Du denn sowas alles?


----------



## The_S (26. Apr 2007)

Hm, Farbwertberechnung ist logisches denken, aus dem RGB int die Alpha, Red, Green und Blue werte auslesen und wieder zusammensetzen ist Source-Code der Klasse "Color" anschauen, Transparentes Rechteck über das Bild legen ist API-Kenntnis (bzw. 2,5 Jahre Java-Erfahrung).


----------



## Clip (27. Apr 2007)

Ich habe mir jetzt eine Methode 'reColorize' geschrieben.
	
	
	
	





```
// hier werden die Farben nochmal nachberechnet um sie 'knalliger' zu machen 
	private static int reColorize(int orgColor, int layerColor ,int averageColor){
		int color = averageColor;
		int div = 5;
		
		if (layerColor > orgColor) color +=  ((layerColor - orgColor)  / div);
		if (layerColor < orgColor) color -=  ((orgColor - layerColor )  / div);
		
		color = color < 255 ? color : 255;
		color = color > 0  ? color : 0; 
				
		return color;		
	}
```

Diese benötigt die Originalkanalfarbe eines Pixels, die Layerkanalfarbe und den bereits berechneten Mittelwert. 
Anhand des Teilers 'div' kann der Kontrast eingestellt werden. Je höher der Wert, desto näher liegt das Ergebis an dem bereits berechneten Mittelwert. Bei dem Wert 1 ist das Ergebnis sehr knallig  Für meine Zwecke ist der Wert 5 ein guter! Die Farben erscheinen hell und leuchtend, das Originalbild hinter dem Layer ist ebenfalls noch gut zu erkennen.

Die Methode sollte noch vernünftig in das Gesamtfarbberechnungskonzept eingebunden werden, ansonsten ist sie OK.

Vielen Dank für die Hilfe!


----------

