16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル
"RE:ビットマップを回転描画する"
この発言は #00204 河邦 正 さんのビットマップを回転描画する に対するコメントです
> ビットマップを回転描画する関数です。
#204 の自分が出したコードの一部修正(3ヶ所)です。
回転後の画像の大きさの計算で、
bmpDst.Width と bmpDst.Height の + 1 を取り除きます。
スキャン開始点の座表計算で、
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);
を
exX := (bmpTmp.Width / 2) - (CosValue * (bmpDst.Width / 2 - 0.5))
- (SinValue * (bmpDst.Height / 2 - 0.5));
exY := (bmpTmp.Height / 2) - (-SinValue * (bmpDst.Width / 2 - 0.5))
- (CosValue * (bmpDst.Height / 2 - 0.5));
に変更し、また‘for x...’ループ内の
pointTmp := Point(Round(exX), Round(exY));
を
pointTmp := Point(Floor(exX), Floor(exY)); // uses節に math
に変更してください。
上記の変更は、ビットマップが占める領域の座標と、ピクセルが実際に
占める座標の‘ずれ’(0.5)を正しく換算するための変更です。
以下が、修正後のコードです。
uses Math;
// ビットマップを回転させて 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;
// 修正その1
// 回転後の画像が入る大きさにする
bmpDst.Width := Round(abs(CosValue * bmpTmp.Width)
+ abs(-SinValue * bmpTmp.Height));
bmpDst.Height := Round(abs(SinValue * bmpTmp.Width)
+ abs(CosValue * bmpTmp.Height));
// 修正その2
// 回転コピー先のビットマップのスキャン開始点(0,0)のソース
// ビットマップ座標軸上での位置を計算して exX と exY に代入する
exX := (bmpTmp.Width / 2) - (CosValue * (bmpDst.Width/2-0.5))
- (SinValue * (bmpDst.Height/2-0.5));
exY := (bmpTmp.Height / 2) - (-SinValue * (bmpDst.Width/2-0.5))
- (CosValue * (bmpDst.Height/2-0.5));
// スキャン開始
for y := 0 to bmpDst.Height - 1 do
begin
pdwDstLine := bmpDst.ScanLine[y];
for x := 0 to bmpDst.Width - 1 do
begin
// 修正その3
pointTmp := Point(Floor(exX), Floor(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;
1998/12/06、河邦 正(GCC02240@nifty.ne.jp)
Original document by 河邦 正 氏 ID:(GCC02240)
ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。
Copyright 1996-2002 Delphi Users' Forum
|