Entwickler-Ecke

Multimedia / Grafik - Problem mit Durchschnittsfarbe


Jann1k - Do 17.01.08 01:15
Titel: Problem mit Durchschnittsfarbe
Ich versuche ein bitmap in ein Timage zu laden und dann von diesem Bitmap die Durchschnittsfarbe zu berechnen. Mein Timage hat die Außmaße 20 x 20 Pixel und stretch = true. Mein Problem ist Folgendes, wenn ich die markierte Zeile nicht auskommentiere, wird mir mein Timage nicht angezeigt (visible ist immer auf true) und die function durchschnitt liefert mir (egal bei welchem bild) den selben wert : 1911716 (in RGB 164,43,29).

Mein Quelltext sieht wie folgt aus:

Die Durchschnittsfarbfunction:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
function tmain.durchschnitt:integer;
 var r,g,b:int64;
     I,J,d:integer;
     c:tcolor;
begin
 r:=0;
 g:=0;
 b:=0;

 //rgb werte addieren
 for I:=0 to imeinlesen.width-1 do
  for j:=0 to imeinlesen.height-1 do
  begin
     c:=imeinlesen.picture.Bitmap.canvas.Pixels[I,J];
     r:=r+GetRValue(d);
     g:=g+GetGValue(d);
     b:=b+GetBValue(d);
  end;

  //teilen durch pixelanzahl
  D:=imeinlesen.width *imeinlesen.Height;
  r:=round(r/d);
  g:=round(g/d);
  b:=round(b/d);


  //farbausgabe
  c:=rgb2tcolor(r,g,b);
  result:=c;

end;



Die function rgb2tcolor hab ich aus diesem thread

http://www.delphi-forum.de/viewtopic.php?t=26472&highlight=rgb2tcolor


Delphi-Quelltext
1:
2:
3:
4:
function tmain.RGB2TColor(r,g,b : byte):TColor;
begin
  result := r + (g shl 8) + (b shl 16);
end;



Und der eigentliche Aufruf davon findet in einem Button statt:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure Tmain.Button1Click(Sender: TObject);
begin
  if openpicturedialog.execute then
  begin
   imeinlesen.Picture.LoadFromFile(openpicturedialog.filename);
   showmessage(inttostr(durchschnitt));  //<---markierte Zeile
  end;
end;



Ich weiß echt nicht woran das liegt, die functionen scheinen zu stimmen, wenn ich durchschnitt mit TImages aufrufe, in denen zur Programmierzeit Bilder geladen werden, scheint das wunderbar zu klappen. Setz ich vor die markeirte Zeile ein application.processmessages oder ein imeinlesen.repaint dann seh ich zwar das Timage, aber die Werte von Durchschnitt bleiben falsch.


uko - Do 17.01.08 07:05

Hallo,

mir ist aufgefallen, daß deine Durchschnittsberechnung eigentlich nie was sinnvolles liefern dürfte:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
 //rgb werte addieren
 for I:=0 to imeinlesen.width-1 do
  for j:=0 to imeinlesen.height-1 do
  begin
     // hier liest Du den Farbwert in eine Variable c ein 
     c:=imeinlesen.picture.Bitmap.canvas.Pixels[I,J];

     // die nun komplett ignoriert wird: sollte das 'd' hier nicht 'c' sein?
     r:=r+GetRValue(d);
     g:=g+GetGValue(d);
     b:=b+GetBValue(d);
  end;


Grüße,
Uli


Kroko - Do 17.01.08 07:35

Ich würde es so tun:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
function tmain.durchschnitt:integer;
 var r,g,b:int64;
     I,J,d:integer;
     c:tcolor;
begin
 r:=0;
 g:=0;
 b:=0;

 //rgb werte addieren
 for I:=0 to imeinlesen.picture.bitmap.width-1 do
  for j:=0 to imeinlesen.pciture.bitmap.height-1 do
  begin
     c:=imeinlesen.picture.Bitmap.canvas.Pixels[I,J];
     Inc(r,GetRValue(c)); // c verwenden
     Inc(g,GetGValue(c));
     Inc(b,GetBValue(c));
  end;

  //teilen durch pixelanzahl
  D:=imeinlesen.picture.Bitmap.width *imeinlesen.picture.bitmap.Height;
  r:=round(r/d); //ev. reicht div : R := R div D;
  g:=round(g/d);
  b:=round(b/d);

  //farbausgabe
  result:=(b shl 16or (g shl 8or r;
end;


Jann1k - Do 17.01.08 16:36

Danke schon mal für die Antworten, ihr habt vollkommen recht, da muss wirklich c anstatt d hin, aber das Grundproblem bleibt. Irgendwie erkennt er die Pixelfarbe im Bild nicht richtig, ich hab mir das mal genauer angeschaut, c ist immer gleich -1, das führt dazu das die rgb werte am ende immer 255,255,255 sind. Kennt sich irgendjemand genauer damit aus, warum er die Pixelfarbe nicht erkennen will bzw. was ich falsch mach?


Kroko - Do 17.01.08 17:14

Was passiert eigentlich, wenn Du keinen Umweg über TImage gehst, sondern die Datei direkt per TBitmap.LoadFromFile in ein Bimap lädst?


Jann1k - Do 17.01.08 17:56

Dann kommt ne Fehlermeldung mit dem Bitmap und ich weiß jetzt woran das die ganze Zeit lag. Ich lade die ganze Zeit jpegs und keine bitmaps, da kann das ganze ja auch nicht funktionieren...


Yogu - Do 17.01.08 18:53

Wenn du JPEGs trotzdem benutzen willst, kannst du mit


Delphi-Quelltext
1:
Bitmap.Assign(Jpeg);                    

ein JPEG in eine Bitmap-Instanz importieren.