![]() |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Zitat:
In der Funktion
Delphi-Quellcode:
steht in der vorletzten Zeile
GetAvgColor(Dsn:String):TColor;
Code:
Ändere das bitte in
GetAvgColor(Bmp);
Code:
Hintergrund ist, dass ich ursprünglich die Funktion
Result:=GetAvgColor(Bmp);
Delphi-Quellcode:
hatte, also die, mit einer Bitmap als Parameter.
GetAvgColor(Bmp:TBitmap):TColor;
Die Funktion mit dem Dateinamen als Parameter habe ich später hinzugefügt, aber nicht mehr getestet. Dummerweise hatte ich da vergessen, Result zu setzen. |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Zitat:
|
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Zitat:
Dein Code ist fast voll ok so. Einzig bei der Auswertung von col.... Du musst darauf achten, dass TGPColor (anders als TColor!) wie folgt die Farbe speichert: ARGB d.h. ALPHA ROT GRÜN BLAU Und die von dir verwendeten Winapi.Windows TColor Funktionen GetRValue... rechnen mit (A)BGR=(ALPHA) BLAU GRÜN ROT. Du willst ein Resultat in TColor: Wenn du GetRValue auf col : TGPColor anwendest wirst du den Blauanteil der Farbe erhalten. Entsprechend: Wenn du GetBValue auf eine TGPColor anwendest wirst du den Rotanteil erhalten. Testen könntest du die Sache zum Beispiel so. Du erstellst eine hbit: TBitMap von der Grösse 500x500. Wir setzen alle Pixel auf RGB(255,128,64). Das Pixel (0,0) auf RGB(0,0,0).
Delphi-Quellcode:
Nun lässt du deine Funktionen auf hbit (mit anderen Farben auch prüfen!) los.
hbit := TBitMap.Create;
hbit.SetSize( 500, 500 ); for x := 0 to hbit.Height-1 do for y := 0 to hbit.Width-1 do hbit.Canvas.Pixels[x,y] := rgb(255,128,64); hbit.Canvas.Pixels[0,0] := rgb(0,0,0); fn := 'C:\Users\micha\Desktop\test.bmp'; hbit.SaveToFile( fn ); hbit.Free; TiGü via scanline liefert - da dort nach dem Summieren div anzahlpixels (statt trunc(summe/anzahlpixels+0.5) verwendet wird - als Durchschnittsfarbe (254,127,63). Nun lässt du die Funktion auf grizzlys GDI+ Idee, bzw. deine Lösung los: Du erhältst wie erwartet (255,128,64). |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
@KodeZwerg:
In #16 wurde in den Raum geworfen, ob man nicht einfach ein Resize auf 1x1 Pixel machen kann. Ich hab das mal geprüft und in meiner Funktion TestGetAvgColor; vor dem Bmp.Free folgendes eingefügt:
Delphi-Quellcode:
Das ShowMessage am Ende hab ich abgeändert in:
T3:=GetTickCount;
Bmp2:=TBitmap.Create; Bmp2.PixelFormat:=pf24Bit; Bmp2.SetSize(1,1); SetRect(R,0,0,1,1); Bmp2.Canvas.StretchDraw(R,Bmp); CL3:=Bmp2.Canvas.Pixels[0,0]; Bmp2.Free; T3:=GetTickCount-T3; ShowMessage('$'+IntToHex(CL1,8)+' '+IntToStr(T1-T0)+#13+ '$'+IntToHex(CL2,8)+' '+IntToStr(T2-T1)+#13+ '$'+IntToHex(CL3,8)+' '+IntToStr(T3)); Scheint zu funktionieren, was aber auch daran liegen könnte, dass in der Testprozedur alle Pixel die gleiche Farbe haben. Korrektur: Hab es gerade mit einem echten Bild geprüft. Die Methode, das Bild auf 1x1 Pixel zu reduzieren, liefert eine andere Durchschnittsfarbe. |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Zitat:
Nein das stimmt nicht. Kulturen hin oder her. Schau noch einmal in den Code, um welchen es geht. Dort wird eine Variable r vom Typ integer auf 0 gesetzt. Und danach wird Pixel für Pixel geschaut, welcher Rotanteil vorliegt. Dieser Rotanteil wird jedes Mal zu r addiert. Nun wollen wir herausfinden, wann r frühestens überläuft. r läuft in Kulturen wo der Rotanteil aller Pixel immer 0 ist gar nie über, da r konstant 0 bleibt. D.h. in solchen Kulturen kannst du unendlich viele Rotanteile zu r addieren. Es gibt aber auch Kulturen (zum Beispiel bei gewissen Kulturen im Pferdekopfnebel), in welchen der Rotanteil aller Pixel immer maximal maxbyte = 11111111(bin) = 255(dec) ist. Wenn du dir jetzt überlegen willst, wann es bei der Summenbildung frühestens knallt, dann musst du einen Taschenrechner zur Hand nehmen und eine 0 eintippen. Nun addierst du 255 für Pixel 1, 255 für Pixel 2, 255 für Pixel 3... Nach p Pixeln bist du bei p*255 angelangt. Irgendwann fragst dich, wann p*255 > maxint erreicht wird. Diese Ungleichung kannst du lösen: p>maxint/255. Die Lösung lautet: Nach p>maxint/255 Pixeln läuft r über. |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Zitat:
Ich nehme auch an, dass GDI+ beim Skalieren auf 1x1 nicht oft die gleiche Durchschnittsfarbe berechnet. Du könntest ja auch auf ein 10x10 oder ähnlich skalieren und dort rechnen. Die 1x1 Bitmap Farbe hängt natürlich u.a. vom verwendeten Skalier-Algorithmus ab. Bliebe die Frage: Welche Farbe ein Mensch als die "bessere" Durchschnittsfarbe bewerten würde. Hast du irgendwo einen Link auf wissenschaftliche Literatur (wäre interessant), wo sowas wie eine "Durchschnittsfarbe" besprochen wird. Ich nehme an, dass in der Grafikbranche nicht einfach über RGB addiert und der Mittelwert genommen wird. Da werden doch sicher andere Modelle "bemüht"? |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Liste der Anhänge anzeigen (Anzahl: 1)
@Amateurprofi: Ich war da auch blind, es klappt nun bestens!
@Michael II: Ich habe es nun hinbekommen das alles funktioniert! Danke mit den Alpha-Kanal Tipp, das hat mich irgendwie auf die richtige Spur geführt auch wenn ich teilweise nur Bahnhof verstanden habe ;) Im Anhang, für alle Interessierten, meine Testergebnisse bei einem Durchlauf incl Abbildung des GDI+ codes. (GetRed() GetGreen() GetBlue() war die Lösung, so hoffe ich jedenfalls) Ich muss fairer Weise sagen ich die Topic falsch betitelt habe, es müsste nicht Bitmap sondern Bild heißen. Ich werde es nochmal testen wenn ich eine "TBitmap bzw HBITMAP" Konvertierung eingepflanzt habe damit es mehr als nur reine Bitmaps annehmen kann. Ausgangspunkt sollte in allen Fällen ein WIC-Image sein, damit ich alles was Microsoft verarbeitet auch unterstützen kann. Diese Konvertierung von WIC nach ein passendes Bitmap-Format wird sich dann natürlich negativ auswirken und wahrscheinlich den jetzigen Vorsprung zumindest etwas egalisieren. Danke Euch beiden für diese sehr Interessanten Beiträge!! |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Zitat:
Reine Bitmaps habe ich gar keine zum Testen damit ich auch Eure (Assembler und GDI+) besser testen kann. |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Zitat:
Anstelle auf 1x1, wäre meine Überlegung ein sinnvolles Resize erst dann durchzuführen wenn Int64 für die Berechnung nicht mehr ausreicht. Es wurden zwar viele Zahlen in den Raum geworfen, aber wie sollte man da Sinnvoll vorgehen?... Ein Bild besteht ja aus zwei Dimensionen, ein Int64 ist nur eine. Was ich meine, gibt es eine logik die so etwas berechnen kann, ein bild kann ja 100 million pixel Hoch aber nur 1 pixel breit sein. Andersrum genauso. Oder eben in beide Dimensionen sehr sehr viele Pixel besitzen. Also es gäbe halt mehr als nur eine Möglichkeit diese berechnung hier zum platzen zu bringen. Ein Resize auf eine Dimension die es nicht zum platzen bringt, das wäre das Sahnetörtchen ;-) |
AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
Zitat:
High(Uint64)=2^64-1=18446744073709551615 Da du momentan RGB Werte im Bereich 0..255 verwendest, kannst du nach dem grössten p (Anzahl Pixel deiner Bitmap) suchen, welches p*255 <= 1844674407370955165 erfüllt. p(max)=72’340’172’838’076’673 D.h. du kannst enorm grosse Bitmaps (mit maximal p(max) Pixeln) verarbeiten. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:40 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz