お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"ビットマップ回転描画"



 ビットマップを回転描画する関数です。

 Delphi3 の新機能に頼っているので C++Builder 1、Delphi 2、では使えま
せん。
 このくらいのコード量でビットマップが回転できるのは Delphi3 の新機能
のおかげです。C++Builder がバージョンアップして Delphi3 の機能を含むよ
うになば、そのまま使えるようになるでしょう。

// ビットマップを回転させて Canvas に描画する
procedure RotateDraw(Canvas: TCanvas; iX, iY, iAngle: Integer;
  bmpSrc: TBitmap; clBackGround: TColor);
var
  dwBackGround: DWORD;
  CosValue, SinValue: Extended;
  bmpTmp, bmpDst: TBitmap;
  x, y: Integer;
  exX, exY: Extended;
  pointTmp: TPoint;
  pdwDstLine: PDWORD;
begin
  // デフォルトの背景色をビットマップ内のフォーマットに変換する
  dwBackGround := (DWORD(clBackGround) and $ff shl 16)
               or (DWORD(clBackGround) and $ff00)
               or (DWORD(clBackGround) and $ff0000 shr 16);

  // 三角関数の計算結果をキープする
  CosValue := Cos(iAngle * Pi / 180);
  SinValue := Sin(iAngle * Pi / 180);

  bmpTmp := TBitmap.Create;
  try
    // ソースビットマップをコピーしてからフォーマットを pf32Bit にする
    bmpTmp.Assign(bmpSrc);
    bmpTmp.PixelFormat := pf32Bit;

    // 回転後の画像を入れるビットマップの作成
    bmpDst := TBitmap.Create;
    try
      bmpDst.PixelFormat := pf32Bit;

      // 回転後の画像が入る大きさにする
      bmpDst.Width  := Round(abs(CosValue * bmpTmp.Width)
                           + abs(-SinValue * bmpTmp.Height)) + 1;
      bmpDst.Height := Round(abs(SinValue * bmpTmp.Width)
                           + abs(CosValue * bmpTmp.Height)) + 1;

      // 回転コピー先のビットマップのスキャン開始点(0,0)のソースビット
      // マップ座標軸上での位置を計算して exX と exY に代入する
      pointTmp := Point(bmpDst.Width div 2, bmpDst.Height div 2);
      exX := (bmpTmp.Width  / 2) - (CosValue * pointTmp.x)
                                 - (SinValue * pointTmp.y);
      exY := (bmpTmp.Height / 2) - (-SinValue * pointTmp.x)
                                 - (CosValue * pointTmp.y);

      // スキャン開始
      for y := 0 to bmpDst.Height - 1 do
      begin
        pdwDstLine := bmpDst.ScanLine[y];
        for x := 0 to bmpDst.Width - 1 do
        begin
          pointTmp := Point(Round(exX), Round(exY));

          // exX & exY がソースビットマップの有効範囲である場合
          if(0 <= pointTmp.x)and(pointTmp.x < bmpTmp.Width)and
            (0 <= pointTmp.y)and(pointTmp.y < bmpTmp.Height)then
            pdwDstLine^ := PDWORD(PChar(bmpTmp.ScanLine[pointTmp.y])
                                       + (pointTmp.x * sizeof(DWORD)))^
          // exX & exY がソースビットマップの有効範囲外なら背景色にする
          else
            pdwDstLine^ := dwBackGround;

          // odwDstLine, exX & exY を次のピクセルに移す
          Inc(pdwDstLine);
          exX := exX + CosValue;
          exY := exY - SinValue;
        end;
        // exX & exY を次の行の先頭に戻す
        exX := exX + (SinValue - (CosValue * bmpDst.Width));
        exY := exY + (CosValue - (-SinValue * bmpDst.Width));
      end;
      // 回転したビットマップをキャンバスに描画する
      Canvas.Draw(iX, iY, bmpDst);
    finally
      bmpDst.Free;
    end;
  finally
    bmpTmp.Free;
  end;
end;

 特定の色を透過したい場合は、透過したい色を背景色(clBackGround)に指定す
れば透過描画に使用するマスクビットマップが簡単に作成できます。
    procedure TBitmap.Mask(Transparent: TColor);

 これを踏み台にして(しなくてもいいですが)もっと高性能のコンポーネントを
作ってアップロードしてください、期待しています。

                  1997/10/25、河邦 正(GCC02240@niftyserve.or.jp)

Original document by 河邦 正         氏 ID:(GCC02240)


ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum