Home » Tutorials » Grafik und Spiele » Bitmaps
Bitmaps
Bitmap glätten
Das folgende Beispiel ist die ‚tuned-version‘ vom Glätten Tipp bei Tipps & Tricks/Grafik. Es arbeitet ungefähr nach dem selben Prinzip, bildet also immer den Durchschnittswert von benachbarten Pixeln.
Da mit ScanLine der Zugriff auf die Pixel nicht ganz so komfortabel ist wie mit TCanvas.Pixels[x,y], habe ich die Funktion in zwei Funktionen aufgeteilt. Die eine (smoothH) bildet immer den Durchschnittswert von drei Pixeln in horizontaler Lage, die andere (smoothV) in vertikaler Lage.
procedure TForm1.smoothH(Bit: TBitmap); type PixArray = array [1..3] of Byte; var Pict: TBitmap; temp: record v1,v2,v3,n1,n2,n3: Byte; //hier drin werden die drei Farbwerte //vor (v) bzw. nach (n) dem mittleren Pixel gespeichert end; p,pt: ^PixArray; //einmal für das Ausgangsbitmap und einmal das neue w,h: Integer; begin Pict:= TBitmap.Create; // das neue Bitmap Pict.Assign(Bit); // sieht erstmal aus wie das alte... for h:=0 to Bit.Height-1 do begin p:= Bit.ScanLine[h]; pt:= Pict.ScanLine[h]; for w:=0 to Bit.Width-3 do begin Inc(pt); temp.v1:= p^[1]; temp.v2:= p^[2]; temp.v3:= p^[3]; inc(p,2); temp.n1:= p^[1]; temp.n2:= p^[2]; temp.n3:= p^[3]; dec(p); //...bekommt im Gegensatz zum alten pt^[1]:= (temp.v1+temp.n1+p^[1]) div 3; // neue Werte zugewiesen. Das alte pt^[2]:= (temp.v2+temp.n2+p^[2]) div 3; // dient als 'read-only', damit pt^[3]:= (temp.v3+temp.n3+p^[3]) div 3; // kein Wert ein zweites Mal mit einem anderen gemittelt wird. end; end; // Nun noch alt gegen neu tauschen, und fertig mit Teil1. Bit.Assign(Pict); Pict.Free; end; procedure TForm1.smoothV(Bit: TBitmap); type PixArray = Array [1..3] of Byte; var Temp: TBitmap; p1,p2,p3,pt: ^PixArray; h,w,i: Integer; begin // hier muss anders vorgegangen werden, als beim //ersten Mal da ScanLine immer Zeilenweise liest. vertikal // Also für drei Pixel brauchen wir auch drei Zeilen. Temp:= TBitmap.Create; // ...das neue Bitmap... Temp.Assign(Bit); for h:=1 to Bit.Height-2 do begin pt:= Temp.ScanLine[h]; p1:= Bit.ScanLine[h]; p2:= Bit.ScanLine[h+1]; p3:= Bit.ScanLine[h-1]; for w:=0 to Bit.Width-1 do begin For i:=1 to 3 do pt^[i]:= (p1^[i] + p2^[i] + p3^[i]) div 3; // wieder wird nur das neue Bild verändert Inc(p1); Inc(p2); Inc(p3); Inc(pt); end; end; Bit.Assign(Temp); Temp.Free; end;
Nun wird mit einem Ausgangsbitmap smoothH aufgerufen, und danach mit dem neuen smoothV.