AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Bitmap Kantenglättung

Ein Thema von marius0702 · begonnen am 14. Mär 2009 · letzter Beitrag vom 14. Mär 2009
Antwort Antwort
marius0702

Registriert seit: 1. Jan 2008
40 Beiträge
 
#1

Bitmap Kantenglättung

  Alt 14. Mär 2009, 12:52
ich hab heute eine kantenglättung für bitmaps geschrieben und wollte mal fragen ob man das villeicht noch etwas beschleunigen kann .
mein pc braucht für ein bild mit 299x342 pixeln und 1xAA ca 3,8 ms.
für größere bilder und für animationen wären ein paar ms weniger nicht schlecht .

Delphi-Quellcode:

function AA(bmp:tbitmap;haeufigkeit:integer;intensitaet:integer;backgroundcolor:tcolor):real;
var
x,y,i:integer;
col2,col4,col5,col6,col8,c1,c2,c3:tcolor;
background:tcolor;
relevance,r,g,b:integer;
b1,b2,b3,b4:pbytearray;

//Zeitmessung
  freq: Int64;
  startTime: Int64;
  endTime: Int64;
  tempbmp:tbitmap;
begin
  QueryPerformanceFrequency(freq);
  QueryPerformanceCounter(startTime);
//Zeitmessung

background:=backgroundcolor;

relevance:=intensitaet+1;

if bmp.PixelFormat<>pf24bit then
bmp.PixelFormat:=pf24bit;

tempbmp:=tbitmap.Create;
tempbmp.Assign(bmp);

for i:=1 to haeufigkeit do begin
  for y:=bmp.Height-2 downto 1 do begin


// ____________
// <-| b1| b1| b1|->
// <-|___|___|___|->
// <-| b2| b2| b2|->
// <-|___|___|___|->
// <-| b3| b3| b3|->
// <-|___|___|___|->

    b1:=bmp.ScanLine[y-1];
    b2:=bmp.ScanLine[y];
    b3:=bmp.ScanLine[y+1];

    b4:=tempbmp.ScanLine[y];

    for x:=1 to bmp.Width-2 do begin

// ____________
// | | 2 | |
// |___|___|___|
// | 4 | 5 | 6 |
// |___|___|___|
// | | 8 | |
// |___|___|___|



    //pixel mitte-oben
    r:=b1[(x)*3+2];
    g:=b1[(x)*3+1];
    b:=b1[(x)*3+0];
    col2:=rgb(r,g,b);

    //pixel mitte-links
    r:=b2[(x-1)*3+2];
    g:=b2[(x-1)*3+1];
    b:=b2[(x-1)*3+0];
    col4:=rgb(r,g,b);

    //pixel mitte-mitte
    r:=b2[(x)*3+2];
    g:=b2[(x)*3+1];
    b:=b2[(x)*3+0];
    col5:=rgb(r,g,b);

    //pixel mitte-rechts
    r:=b2[(x+1)*3+2];
    g:=b2[(x+1)*3+1];
    b:=b2[(x+1)*3+0];
    col6:=rgb(r,g,b);

    //pixel unten-mitte
    r:=b3[(x)*3+2];
    g:=b3[(x)*3+1];
    b:=b3[(x)*3+0];
    col8:=rgb(r,g,b);



// ____________
// | | 2 | |
// |___|___|___|
// | 4 | 5 | |
// |___|___|___|
// | | | |
// |___|___|___|
     c1:=col2;
     c2:=col4;

     if (c1<>col5) and (c2<>col5) and (col5=background) then begin

       b4[x*3+2]:=(getrvalue(c1)+getrvalue(c2)+getrvalue(col5)*relevance) div (3+relevance);
       b4[x*3+1]:=(getgvalue(c1)+getgvalue(c2)+getgvalue(col5)*relevance) div (3+relevance);
       b4[x*3+0]:=(getbvalue(c1)+getbvalue(c2)+getbvalue(col5)*relevance) div (3+relevance);

     end;

// ____________
// | | 2 | |
// |___|___|___|
// | | 5 | 6 |
// |___|___|___|
// | | | |
// |___|___|___|
     c1:=col2;
     c2:=col6;

     if (c1<>col5) and (c2<>col5) and (col5=background) then begin

       b4[x*3+2]:=(getrvalue(c1)+getrvalue(c2)+getrvalue(col5)*relevance) div (3+relevance);
       b4[x*3+1]:=(getgvalue(c1)+getgvalue(c2)+getgvalue(col5)*relevance) div (3+relevance);
       b4[x*3+0]:=(getbvalue(c1)+getbvalue(c2)+getbvalue(col5)*relevance) div (3+relevance);

     end;


// ____________
// | | | |
// |___|___|___|
// | 4 | 5 | |
// |___|___|___|
// | | 8 | |
// |___|___|___|
     c1:=col8;
     c2:=col4;

     if (c1<>col5) and (c2<>col5) and (col5=background) then begin

       b4[x*3+2]:=(getrvalue(c1)+getrvalue(c2)+getrvalue(col5)*relevance) div (3+relevance);
       b4[x*3+1]:=(getgvalue(c1)+getgvalue(c2)+getgvalue(col5)*relevance) div (3+relevance);
       b4[x*3+0]:=(getbvalue(c1)+getbvalue(c2)+getbvalue(col5)*relevance) div (3+relevance);

     end;


// ____________
// | | | |
// |___|___|___|
// | | 5 | 6 |
// |___|___|___|
// | | 8 | |
// |___|___|___|
     c1:=col8;
     c2:=col6;

     if (c1<>col5) and (c2<>col5) and (col5=background) then begin

       b4[x*3+2]:=(getrvalue(c1)+getrvalue(c2)+getrvalue(col5)*relevance) div (3+relevance);
       b4[x*3+1]:=(getgvalue(c1)+getgvalue(c2)+getgvalue(col5)*relevance) div (3+relevance);
       b4[x*3+0]:=(getbvalue(c1)+getbvalue(c2)+getbvalue(col5)*relevance) div (3+relevance);

     end;

    end;
  end;
bmp.Assign(tempbmp);
end;


//Zeitmessung
  QueryPerformanceCounter(endTime);

  result:=(endTime - startTime) * 1000 / freq;
//Zeitmessung
end;

procedure TForm1.BAAClick(Sender: TObject);
begin
Lzeit.Caption :=
    floattostr(AA(image1.Picture.Bitmap,spinedit_haeufigkeit.Value,spinedit_intensitaet.Value,clblack))+' ms';
end;
die kantenglättung glättet nicht alles sondern nur die übergänge von der hintergrundfarbe zu den restlichen farben.

[edit=mkinzler]Code umgebrochen wegen Layout Mfg, mkinzler[/edit]
  Mit Zitat antworten Zitat
Cicaro

Registriert seit: 9. Feb 2005
285 Beiträge
 
Delphi 7 Personal
 
#2

Re: Bitmap Kantenglättung

  Alt 14. Mär 2009, 13:45
Falsches Forum für diesen Thread.
  Mit Zitat antworten Zitat
Benutzerbild von lbccaleb
lbccaleb

Registriert seit: 25. Mai 2006
Ort: Rostock / Bremen
2.037 Beiträge
 
Delphi 7 Enterprise
 
#3

Re: Bitmap Kantenglättung

  Alt 14. Mär 2009, 13:55
Zitat von Cicaro:
Falsches Forum für diesen Thread.
Wieso das denn??
Martin
MFG Caleb
TheSmallOne (MediaPlayer)
Die Dinge werden berechenbar, wenn man die Natur einer Sache durchschaut hat (Blade)
  Mit Zitat antworten Zitat
Benutzerbild von SirThornberry
SirThornberry
(Moderator)

Registriert seit: 23. Sep 2003
Ort: Bockwen
12.235 Beiträge
 
Delphi 2006 Professional
 
#4

Re: Bitmap Kantenglättung

  Alt 14. Mär 2009, 14:02
Weil es sich hier nicht darum handelt ein Projekt mit anderen zu haben.
Jens
Mit Source ist es wie mit Kunst - Hauptsache der Künstler versteht's
  Mit Zitat antworten Zitat
14. Mär 2009, 14:02
Dieses Thema wurde von "SirThornberry" von "Projekte" nach "VCL / WinForms / Controls" verschoben.
Laufi

Registriert seit: 21. Mär 2006
86 Beiträge
 
#6

Re: Bitmap Kantenglättung

  Alt 14. Mär 2009, 14:27
Hallo!

Ist es absichtlich das der code redundat ist und nicht schön aussieht damit man das selber macht!

Liebe Grüsse
Laufi
  Mit Zitat antworten Zitat
Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#7

Re: Bitmap Kantenglättung

  Alt 14. Mär 2009, 15:16
Ich würde zuersteinmal das Format auf 32Bit umstellen, weil 32Bit-Werte vom Prozessor in der regel schneller verarbeitet werden können (auf 32Bit-systemen) als 24Bit-Werte.

Ich würde vor der eigentlichen Optimierung aber deinen Code umstrukturieren!

Zuersteinmal solltest du den Aufbau der Funktion zu überdenken, d.h. versuchen, den Code sinnvoll in Subfunktionen auszulagern. Es gibt sehr viele Codeblöcke die durch Copy&Paste entsatnden sind. Copy&Paste ist immer ein starkes Anzeichen dafür, dass man den Code ausgliedern sollte. Bitte gib deinen Variablen aussagekräftigere Namen. Dein aktueller Code ist trotz Kommentierung für einen Außenstehenden schwer nachzuvollziehen.

Fangen wir mal an, aufzuräumen:
Ich frage mich z.B., warum du die Variablen col2 - col8 hast, aber nie direkt benutzt, sondern immer in c1 und c2 kopierst. Ich vermute, du hast den Code mehrfach kopiert und eingefügt, und warst zu faul ihn zu verändern. Genau aus diesem Grund gibt es Sub-Routinen! Performanceeinbußen sind dadurch in der Regel nicht zu erwarten, weil die Funktion vom Compiler in der Regel ge-inlined werden sollte, wenn nicht, kann man dies durch function MyFunction(...); inline; erzwingen.

Das hier ließe sich super ausgliedern:
Delphi-Quellcode:
c1:=col2;
c2:=col4;

if (c1<>col5) and (c2<>col5) and (col5=background) then begin
  b4[x*3+2]:=(getrvalue(c1)+getrvalue(c2)+getrvalue(col5)*relevance) div (3+relevance);
  b4[x*3+1]:=(getgvalue(c1)+getgvalue(c2)+getgvalue(col5)*relevance) div (3+relevance);
  b4[x*3+0]:=(getbvalue(c1)+getbvalue(c2)+getbvalue(col5)*relevance) div (3+relevance);
end;

{ ... weiterer gleichartiger Code ...}
Hier mein (ungetesteter) Code:
Delphi-Quellcode:
function GetAntialiasedValue(Center, Value1, Value2: Byte; {relevance:integer}): byte; inline;
// relevance ist auskommentiert, muss man nicht unbedingt als Parameter übergeben
begin
  result := (Value1+Value2+Center*relevance) div (3+relevance);
end;

procedure ProcessPixel(PixelPointer: PByte; Center, Color1, Color2: TColor); inline;
begin
  PixelPointer := GetAntialiasedValue(GetBValue(Center), GetBValue(Color1), GetBValue(Color2));
  inc(PixelPointer);
  PixelPointer^ := GetAntialiasedValue(GetGValue(Center), GetGValue(Color1), GetGValue(Color2));
  inc(PixelPointer);
  PixelPointer^ := GetAntialiasedValue(GetRValue(Center), GetRValue(Color1), GetRValue(Color2));
end;

...

if col5 = background then
begin
  if (col2<>col5) and (col4<>col5) then begin
    ProcessPixel(@b4[x*3], col5, col2, col4);
  if (col2<>col5) and (col6<>col5) then begin
    ProcessPixel(@b4[x*3], col5, col2, col6);
  if (col8<>col5) and (col6<>col5) then begin
    ProcessPixel(@b4[x*3], col5, col8, col6);
  if (col8<>col5) and (col6<>col5) then begin
    ProcessPixel(@b4[x*3], col5, col8, col6);
end;
Siehst du, wie viel übersichtlicher das ganze jetzt ist? Dadurch wird es viel einfacher, Optimierungen durchzuführen, weil man zusammenhängenden Code immer sofort mit einem Blick erfassen kann. Z.B. fällt nun das häufige @b4[x*3] auf: Hier könnte man stattdessen einen Pointer benutzen, denn man nach jedem Durchlauf der x-Schleife um 3 (bzw 4, bei 32Bit) erhöht. Zudem habe ich die if-Abfragen verschachtelt, sodass die weiteren Abfragen nicht mehr durchgeführt werden müssen, wenn die erste bereits False ergibt. Auch dies ist ein Schluss, der durch die bessere Übersichtlichkeit begünstigt wurde. Desweiteren sparst du durch die Funktionen eine Menge Variablen!

Das ganze ist natürlich noch nicht fertig, bis jetzt wurde auch noch nicht viel optimiert. Als nächstes würde ich wie gesagt versuchen, von den Arrays wegzukommen, und stattdessen komplett auf Pointer umzustellen, was wohl noch am ehesten einen Geschwindigkeitsschub geben sollte. Ansonsten kann hier wohl nicht mehr sehr viel Performance herausgeholt werden. Trotzdem ist ein "Refactoring" sinnvoll, um den Code verständlicher zu machen. Wenn du dir deine alte Funktion in einem Jahr anguckst, wirst du dich erst einmal eine haleb Stunde lang einarbeiten müssen, damit du wieder weißt, was der Code eigentlich macht... ich spreche da aus eigener Erfahrung!

Also vereinfache das ganze noch ein bisschen, vielleicht fällt dir noch die ein oder andere Optimierungsmöglichkeit dabei auf.
  Mit Zitat antworten Zitat
marius0702

Registriert seit: 1. Jan 2008
40 Beiträge
 
#8

Re: Bitmap Kantenglättung

  Alt 14. Mär 2009, 17:28
Danke erstmal, für eure beiträge .
sorry das mein code villeicht etwas unübersichtlich ist .
ich werd die vorschläge mal in die funktion einbauen und gucken ob es etwas schneller ist.
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 15. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#9

Re: Bitmap Kantenglättung

  Alt 14. Mär 2009, 17:33
Delphi-Quellcode:
tempbmp:=tbitmap.Create;
tempbmp.Assign(bmp);
Man braucht "bmp" nicht auf "tempbmp" kopieren, da "tempbmp" sowieso überschrieben wird.
Delphi-Quellcode:
tempbmp:=tbitmap.Create;
tempbmp.Width := bmp.Width;
tempbmp.Height:= bmp.Height;
tempbmp.PxelFormat := bmp.PixelFormat;
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:17 Uhr.
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