Delphi-PRAXiS
Seite 3 von 6     123 45     Letzte »    

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Durchschnittsfarbe eines Bitmap "schnell" ermitteln (https://www.delphipraxis.net/207856-durchschnittsfarbe-eines-bitmap-schnell-ermitteln.html)

KodeZwerg 11. Mai 2021 15:57

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Amateurprofi (Beitrag 1489163)
Hallo KodeZwerg:
Ich hab dir mal etwas zusammengestoppelt.
Aufruf mit GetAvgColor(Dateiname) oder GetAvgColor(Bitmap)
Mit TestGetAvgColor; hab ich das Ergebnis und die Performance getestet und mit der Funktion aus #3 verglichen.
Die zurückgegebenen Durchschnittsfarben sind identisch, die Ausführungszeiten sind dagegen höchst unterschiedlich.

Danke Amateurprofi, dein Code arbeitet zwar schneller aber liefert bei mir kein Ergebnis.
Ich habe ihn gegen den Turbo von TiGü antreten lassen, siehe Anhang.

Muss ich noch eine besondere Einstellung vornehmen damit mir Dein Code einen Farbwert über 0 liefert?

Getestet mit Delphi Rio, 32-bit build, Release, unter Windows 10 64bit aktuellste patches.

Michael II 11. Mai 2021 15:59

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
Zitat:

Zitat von grizzly (Beitrag 1489158)
Interessante Diskussion. Da kommt mir aber noch eine abstruse Idee: Man macht ein "Resize" des Bildes auf 1x1 Pixel großes Bild und schaut sich dann nur noch dieses Pixel an. Läuft das Resize auf der GPU wäre das auch ganz schon flott.
Ich habe natürlich keine Ahnung, wieviel Mühe sich so ein Bildverkleinerungsalgo macht, wenn das Ziel nur noch 1 Pixel groß ist...

Viele Grüße
Michael :duck:

Halt doch noch rasch dazu:
Coole Idee... ;-).

Funktioniert auch gut... und sicher schnell, u.v.a. auch auf dem TrillionK Monitor. Ich habe keine Zeit fürs Messen.

Die Werte sind (was ich auch erwartet habe, GrafikerInnen berechnen den Durchschnittswert wahrscheinlich eher über ein anderes Modell und etwas anders) nicht ganz gleich (wie beim RGB DS Rechnen). Bei einfarbigen Bitmaps aber natürlich identisch.

Man könnte natürlich statt auf ein 1x1 Pixel zu skalieren eine etwas grössere Zielbitmap wählen.

Der Code wird ultrakurz:


GDI+
Delphi-Quellcode:
uses GDIPOBJ, GDIPAPI;

  gr := TGPGraphics.Create( bmap );
  gr.ScaleTransform( 1/bmap.GetWidth, 1/bmap.GetHeight );
  gr.DrawImage( bmap, 0,0 );
  bmap.GetPixel(0,0,col);

Jens01 11. Mai 2021 16:02

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
Zitat:

Bei ganz ganz ganz vielen Pixeln ist der Wert irgendwann so groß, dass die nächste Addition des kleinen Wertes, abgeschnitten wird.
r wird nicht größer als 255, oder?

KodeZwerg 11. Mai 2021 16:08

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
So wie ich es verstanden habe fügt sich ein RBG wert aus 3 DWORDs zusammen.

himitsu 11. Mai 2021 16:21

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
Es ist ein DWORD, dass aus 3+1 Bytes besteht :wink:

KodeZwerg 11. Mai 2021 16:35

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
@Michael II
Nun passiert da was... aber mein Ergebniss ist falsch.
Delphi-Quellcode:
function GetAvgGDIColor(const Filename: string): TColor;
var
  gr: TGPGraphics;
  Bmap: TGPBitmap;
  col: TGPColor;
begin
  Result := 0;
  bmap := TGPBitmap.Create(Filename);
  try
    gr := TGPGraphics.Create( bmap );
    try
      gr.ScaleTransform( 1/bmap.GetWidth, 1/bmap.GetHeight );
      gr.DrawImage( bmap, 0,0 );
      bmap.GetPixel(0,0, col);
      Result := RGB(GetRValue(col), GetGValue(col), GetBValue(col));
    finally
      gr.Free;
    end;
  finally
    bmap.Free;
  end;
end;
Falls Du Dich nochmal reinklinken könntest um mich zu korrigieren, das wäre nett!


Zitat:

Zitat von himitsu (Beitrag 1489174)
Es ist ein DWORD, dass aus 3+1 Bytes besteht :wink:

Mein Fehler!

dummzeuch 11. Mai 2021 17:28

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
Zitat:

Zitat von KodeZwerg (Beitrag 1489156)
Auf Int64 ist es bereits umgestellt, aber auch das hat seine Grenzen.
Mir fehlt da die Erfahrung wie man es "abfangen" könnte damit die Berechnung einfach ab einer gewissen Zahl aufhört weiterzuzählen, würde es aber gerne zur Sicherheit mit einbauen.

Man könnte auf einen möglichen Überlauf prüfen und Zwischen-Mittelwerte bilden, die dann hinterher zusammengerechnet werden.

Mathematisch gilt ja:
Code:
 a1 + a2 + a3 + a4    a1    a2    a3    a4     a1 + a2     a3 + a4
------------------- = --- + --- + --- + --- = --------- + ---------
      4                4     4     4     4        4           4
Und bei hohen Zahlen sind evtl. Rundungsfehler eher unwichtig.

Rollo62 11. Mai 2021 18:01

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
Zitat:

Zitat von Michael II (Beitrag 1489144)
maxint=2^31-1 speichern.
s > sqrt((2^31-1)/255))

Oha verrechnet, Du hast ja Recht :oops:
Habe auf die Schnelle mit Cardinal gerechnet, und mangels Taschenrechner nur geschätzt.

Stimmt Integer ist signifikant kleiner, trotzdem würde ich mit dem vollen Umfang und 8-Bit rechnen, wieso -1 ?
s > sqrt( (2^31)/256 ) = sqrt((2^31)/2^8 ) = sqrt( (2^31-8) ) = sqrt( 2^23 ) = 2^( 23 / 2 ) = 2^11.5 = 2896
Also ich komme auf 2896x2896, ist wirklich zu wenig.

Michael II 11. Mai 2021 18:53

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
Zitat:

Zitat von Rollo62 (Beitrag 1489191)
Zitat:

Zitat von Michael II (Beitrag 1489144)
maxint=2^31-1 speichern.
s > sqrt((2^31-1)/255))

Oha verrechnet, Du hast ja Recht :oops:
Habe auf die Schnelle mit Cardinal gerechnet, und mangels Taschenrechner nur geschätzt.

Stimmt Integer ist signifikant kleiner, trotzdem würde ich mit dem vollen Umfang und 8-Bit rechnen, wieso -1 ?
s > sqrt( (2^31)/256 ) = sqrt((2^31)/2^8 ) = sqrt( (2^31-8) ) = sqrt( 2^23 ) = 2^( 23 / 2 ) = 2^11.5 = 2896
Also ich komme auf 2896x2896, ist wirklich zu wenig.

Cardinal ist in D32bit und D64bit 32Bits lang, ohne Vorzeichen. Du hast also rund zwei Mal so viele Zahlen>0 wie bei integer - und damit sqrt(2) mal mehr maximale Bitmap-Seitenlänge.

Zu deiner Frage wegen wieso -1. Du hast das Vorzeichenbit vergessen. Die grösste positive integer Zahl (maxint) sieht so aus m = 011111111 11111111 11111111 11111111. Wenn du zu m 1 addierst, hättest du 10000000 00000000 00000000 00000000 = 2^32. Die Zahl vor 2^32 hat damit den Wert maxint=2^32-1. 2^32 entspricht bei integer dem negativen Wert -2^32.
Oder wenn du's lieber via geometrische Reihe rechnen willst:
011111111 11111111 11111111 11111111 hat den Wert
s = 2^0+2^1+2^2+....+2^30
und 2s = 2^1+...+2^31
Subtrahierst du von Zeile 2 Zeile 1 ergibt sich s=2^31-2^0 = 2^31-1.

Zu deinem Einwand, man sollte durch 2^8=256 teilen. Kurze Antwort: Nein. Lange Antwort: r liegt im Bereich [0..255] und nicht im Bereich [0..256]. Du musst dir also überlegen wie oft 255 in 2^32-1 Platz hat => (2^32-1)/255 Mal.

himitsu 11. Mai 2021 18:58

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln
 
Nein, man muß gucken, wie oft 256 Platz hat,
denn die 0 ist auch ein gültiger Wert.

1..255 bzw. 0..254 wäre Platz für 255.



Aber keine Sorge, auch andere vergessen die 0 gern.
Daher wurde die Zahl 0 in vielen Kulturen auch erst sehr spät erfunden.


Alle Zeitangaben in WEZ +1. Es ist jetzt 08:37 Uhr.
Seite 3 von 6     123 45     Letzte »    

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz