アンチエイリアス処理

画像を放り込むと、その画像を縦横各1/2に縮める関数。単純にStretchDrawで縮めるより綺麗に仕上がる。
見て分かるように内部で全ピクセルを舐めるので、連続的かつ高頻度に処理が発生する場合は重くなりそうだけど、時計などの描画ならこれで十分だろうと思われる。
一応私に出来る限りの高速化はしてある(一番内側で for i:=0 to 2 do を使わないのは、それなりの理由がある)けど、あとは各自でチューニングすべし。

procedure BmpAntiAliasByRef(var aBmp: TBitmap);
var aW, aH, bW, bH: integer;
    aX, aY, sX, sY, aXs, sXs: integer;
    pABits: array[0..2] of PByteArray;
begin
  // 与えられたBitmapに縦横各50%の圧縮を行い
  // 擬似的なアンチエイリアス処理を行う。
  // Bitmap自体のサイズも変更される。
  // 32bitモード専用

  bW := aBmp.Width;
  bH := aBmp.Height;
  aW := bW div 2;
  aH := bH div 2;

  // pABits 0=WriteLine
  //        1=ReadLine(Base)
  //        2=ReadLine(Base+1)

  // Y軸ループ
  for aY:=0 to aH-1 do begin
    sY := aY * 2;
    pABits[0] := aBmp.ScanLine[aY];
    pABits[1] := aBmp.ScanLine[sY];
    pABits[2] := aBmp.ScanLine[sY+1];
    // X軸ループ
    for aX:=0 to aW-1 do begin
      // 平均化して書き戻し(4で割るのは2ビットシフトと同意)
      aXs := aX  * 4; // 書き戻しX軸
      sX  := aXs * 2; // 参照先X軸
      sXs := sX  + 4; // 参照先X軸(1つ右)
      pABits[0][aXs]   :=
        (pABits[1][sX]   + pABits[1][sXs] +
         pABits[2][sX]   + pABits[2][sXs]  ) shr 2;
      pABits[0][aXs+1] :=
        (pABits[1][sX+1] + pABits[1][sXs+1] +
         pABits[2][sX+1] + pABits[2][sXs+1]) shr 2;
      pABits[0][aXs+2] :=
        (pABits[1][sX+2] + pABits[1][sXs+2] +
         pABits[2][sX+2] + pABits[2][sXs+2]) shr 2;
    end;
  end;
  aBmp.Width  := aW;
  aBmp.Height := aH;
end;

使用目的によっては、最後のサイズ変更を行わなくてもいい場合も考えられる(処理後にbitblt転送するから不要、とか)。
ビット単位の処理を行っていて見た目に分かりやすいので、この処理をちょっと改造すればオリジナルの画像フィルタを作ることは容易と思われる。