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.