Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Durchschnittsfarbe eines TBitmap via Scanline? (https://www.delphipraxis.net/107065-durchschnittsfarbe-eines-tbitmap-via-scanline.html)

Cyberstorm 21. Jan 2008 18:28


Durchschnittsfarbe eines TBitmap via Scanline?
 
hallo.

ich bin gerade dabei eine funktion zu schreiben, die mir als rückgabewert vom typ TRGB die durchschnittsfarbe eines bestimmten bereiches eines Tbitmaps liefert.

ich habe sozusagen einen x und y startpunkt und eine bestimmte höhe und breite.
die funktion muss so fix wie möglich sein, weil sie auf ca. 200.000 bilder mit jeweils ca. 100 durchscnittswerte angewandt wird und das leidernicht einmalig.

ich dachte an scanline aber weis nicht genau, wie ich an die sache rangehen soll :/.


liebe grüße
konrad h.

alzaimar 21. Jan 2008 19:01

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
Na ganz einfach:
Bitmap auf 24bit Farbtiefe einstellen, per Scanline die einzelnen Pixel auslesen und für den R, G und B-Wert getrennt den Mittelwert bilden.

Muetze1 21. Jan 2008 19:02

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
Empfehlung: pf32bit nutzen und der Rest bleibt gleich.

alzaimar 21. Jan 2008 19:15

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
Wieso 32bit?

himitsu 21. Jan 2008 19:28

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
nja, eigentlihch wär's doch am schnellsten, wenn er jede BitBreite unterstützt ... umrechnen braucht ja och noch Zeit.

Aber fotos sind meißt eh in 24bit vorliegend, also würde es schon reichen. :gruebel:


[add]
pf32bit: bestimmt wegen dem "direktem" Zugriff

32-Bit-Prozessor halt :angel:

oder wie?

Muetze1 21. Jan 2008 20:37

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
Zitat:

Zitat von alzaimar
Wieso 32bit?

Weil der Prozessor bei jedem Zugriff auf eine ungerade Adresse 2 Lesezyklen macht um den Speicherinhalt zu bekommen. Wenn es eine 32 Bit aligned Adresse ist nur einen. Somit ist bei einem pf24bit Bitmap nur jeder 4. Pixel aligned, somit ist der Zugriff mit 24 Bit deutlich langsamer als bei 32 Bit. Durch TLB und sonstiges CPU Features versucht man zwar genau diese unnötigen Zyklen zu vermeiden bzw. schon nebenbei durchzuführen, aber trotzdem ist es langsamer, auch wenn pro Pixel bei 32 Bit die Daten 8 Byte grösser sind. Das macht aber in dem Sinne nichts, da bei einer ungerade Adresse eh 64 Bit eingelesen werden um dann die unnötigen Bytes wieder weg zu werfen.

Also: Wenn es schon RGB Werte sein sollten, dann immer TRGBQuad, also pf32bit. Wir wollen der CPU ja nicht unnötig Arbeit machen, oder?

alzaimar 21. Jan 2008 21:13

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
@Muetze1: Danke. Kapiert. :freak:

Cyberstorm 21. Jan 2008 23:07

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
ok, danke soweit. ich werde mich mal ransetzen!

Cyberstorm 22. Jan 2008 06:07

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
also ich habe viel gegrübelt und stehe denk technisch immernoch vor problemen :).

nochmal zum problem: ich will von vielen bildern (alle 280x210 --> 4 zu 3) durchschnittswerte von bestimmten pixelbereichen ermitteln, also sozusagen das bild gröber auflösen. dazu soll wirklich jeder pixel mit einbezogen werden. dies soll cpu technisch so schnell wie möglich passieren.
ich zeig euch einfach mal, wasich bisher an code habe:

Delphi-Quellcode:
const
  TestPointsX = 20;
  TestPointsY = 15;
  ImageHeight = 210;
type
  TRefPoints = array[1..TestPoints, 1..TestPoints] of TRGBQuad;

  TJPEGBMP = class (TJpegImage)
  public
    property Bitmap;
  end;

procedure GetRefPoints(FileName: String);
var
  t: TImage;
  i, j, x: Integer;
  P: array[1..ImageHeight] of PRGBQuad;
  average: array[1..TestPointsX, 1..TestPointsY, 1..3] of Integer;
begin
  t:=TImage.Create(nil);
  t.Picture.LoadFromFile(FileName);
  TJPEGBMP(t.Picture.Graphic).Bitmap.PixelFormat:=pf32Bit;
  for i:=1 to 210 do P[i]:=TJPEGBMP(t.Picture.Graphic).Bitmap.ScanLine[i-1];
end;
ich dachte mir, ersteinmal das komplette bild per scanline einzuscannen damit ich das nicht irgendwo doppelt machen muss.
weiterhin war meine idee, die werte für jeweils r g b in den average array zu addieren und am ende den durchschnitt für den TRefPoints array in Byte rgb werte umzurechnen.

der code klappt insoweit, dass ich zumindest per p[0].rgbRed den richtigen wert für pixel 0/0 bekomme und inc(p[0]) liefert auch korrekt pixel 1/0 usw.

bin nun aber ein wenig am verzweifeln, wie ich die schleife zum erstellen der durchscnittswerte aufziehen soll.
mir schwirren sachen wie:
Delphi-Quellcode:
for i:=1 to 210 do

  for x:=1 to TestPoints
  for i:=1 to (210 div testpoints) do
   for j:=1 to (280 div testpoints) do
    begin

    end;


   //last
  for i:=(210 - (210 mod testpoints)) to (210 mod testpoints) do
   for j:=(280 - (280 mod testpoints)) to (280 mod testpoints) do
im kopf rum aber ich kriegs einfach nicht zuende gedacht.

villeicht kann mir ja jemand auf die sprünge helfen :(.

grüße
konrad

Cyberstorm 22. Jan 2008 06:52

Re: Durchschnittsfarbe eines TBitmap via Scanline?
 
passt das?:

Delphi-Quellcode:
//alles auf 0 setzen - initialisieren
for i:=1 to TestPointsX do
 for j:=1 to TestPointsY do
  for k:=1 to 3 do
   average[i, j, k]:=0;

  for i:=1 to TestPointsX do
   for j:=1 to TestPointsY do
    for k:=1 to (280 div TestPointsX) do
      begin
       for l:=1 to (210 div TestPointsY) do
         begin
           average[i, j, 1]:=average[i, j, 1] + p[l*j-1].rgbBlue;
           average[i, j, 2]:=average[i, j, 2] + p[l*j-1].rgbGreen;
           average[i, j, 3]:=average[i, j, 3] + p[l*j-1].rgbRed;
         end;
       Inc(p[l*j-1], 1);
      end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:14 Uhr.
Seite 1 von 2  1 2      

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