图象转动(100分)

  • 主题发起人 主题发起人 林劲松
  • 开始时间 开始时间

林劲松

Unregistered / Unconfirmed
GUEST, unregistred user!
各位大虾,谁可以讲我知,怎样用DELPHI编程来控制已有的位图可绕圆心转动。先谢了。
 
用旋转矩阵,
在自行画到canvas上
|x| * |cos(a) 0|
|y| |0 sin(a)|
(好像是这样)
 
eyes以前回答过,有完整代码,查阅已答问题吧!
 
旋转方程
x'=xcos(a)-ysin(a)
y'=xsin(a)+ycos(a)
 
(d)Rotating Bitmaps

Please take a moment to look through the following code, as I will be discussing it next.

The RotateMain pas file.

///////////////////////////////////////////////////////////////////////

// RotateMain.pas //

// Project: Rotate //

// Copyright (c) 1998 by Jeff Cottingham //

///////////////////////////////////////////////////////////////////////

unit rotatemain;



interface



uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

StdCtrls, ExtCtrls;



type

TForm1 = class(TForm)

Image1: TImage;

Button1: TButton;

Button2: TButton;

Button3: TButton;

procedure FormCreate(Sender: TObject);

procedure FormClose(Sender: TObject; var Action: TCloseAction);

procedure Button1Click(Sender: TObject);

procedure Button2Click(Sender: TObject);

procedure Button3Click(Sender: TObject);

private

{ Private declarations }

public

{ Public declarations }

end;



var

Form1: TForm1;

bitmap1: TBitmap;

bitmap2: TBitmap;

ptr: pByteArray;

newscanline: pByteArray;

implementation



{$R *.DFM}



procedure TForm1.FormCreate(Sender: TObject);

begin

bitmap1 := TBitmap.Create;

bitmap2 := TBitmap.Create;

try

bitmap1.LoadFromFile('Factory.bmp');

bitmap1.PixelFormat := pf8bit;

bitmap2.PixelFormat := pf8bit;

bitmap2.Palette := bitmap1.Palette;

except

ShowMessage('Could not load or alter bitmap');

end;

end;



procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

begin

bitmap1.Free;

bitmap2.Free;

end;



procedure TForm1.Button1Click(Sender: TObject);

begin

Image1.Canvas.FillRect(Image1.Canvas.ClipRect);

Image1.Canvas.Draw(0,0,bitmap1);

end;



procedure TForm1.Button2Click(Sender: TObject);

var

y: integer;

x: integer;

begin

Image1.Canvas.FillRect(Image1.Canvas.ClipRect);

bitmap2.Height := bitmap1.Height;

bitmap2.Width := bitmap1.Width;



for y := 0 to bitmap2.Height - 1 do begin

ptr := bitmap1.ScanLine[y];

newscanline := bitmap2.ScanLine[((bitmap1.Height - 1) - y)];

for x := 0 to bitmap1.Width - 1 do begin

newscanline[x] := ptr[x];

end;

end;



Image1.Canvas.Draw(0,0,bitmap2);

end;



procedure TForm1.Button3Click(Sender: TObject);

var

y: integer;

x: integer;

begin

Image1.Canvas.FillRect(Image1.Canvas.ClipRect);

bitmap2.Height := bitmap1.Width;

bitmap2.Width := bitmap1.Height;



for y := 0 to bitmap1.Width - 1 do begin

newscanline := bitmap2.ScanLine[y];

for x := 0 to bitmap1.Height - 1 do begin

ptr := bitmap1.ScanLine[x];

newscanline[x] := ptr[y];

end;

end;

Image1.Canvas.Draw(0,0,bitmap2);

end;



end.

If you have read preceding code carefully you will notice that you have two bitmaps. bitmap1 is for the original image and bitmap2 is where you are doing your work before you display it. Now let’s take a look at what is going on.

procedure TForm1.FormCreate(Sender: TObject);

begin

bitmap1 := TBitmap.Create;

bitmap2 := TBitmap.Create;

try

bitmap1.LoadFromFile('Factory.bmp');

bitmap1.PixelFormat := pf8bit;

bitmap2.PixelFormat := pf8bit;

bitmap2.Palette := bitmap1.Palette;

except

ShowMessage('Could not load or alter bitmap');

end;

end;

In the preceding code after I create the two bitmaps, bitmap1 and bitmap2, and load an image into bitmap1 you will notice the following line of code.

bitmap2.PixelFormat := pf8bit;

Since you are working with a 256 color bitmap, you must make provisions for the work area (bitmap2) to have the same pixel format as your original image, otherwise it will not display properly, if at all. In the fade example at the end of this section you will be working with a different PixelFormat and there are other factors involved but more on these factors later. PixelFormat pf8bit means that each pixel has eight bits or one byte to hold its color, which in this case is a single palette entry.

Since you are working with a bitmap that might have a palette associated with it, you must also deal with that too. Here I am assigning the handle of bitmap1’s palette to bitmap2:

bitmap2.Palette := bitmap1.Palette;

This will ensure that I am working with the same palette. Without this line of code there are no guarantees that my work area, bitmap2, will display with the proper colors.

So how do you flip an image and display it? The following code accomplishes this.

procedure TForm1.Button2Click(Sender: TObject);

var

y: integer;

x: integer;

begin

Image1.Canvas.FillRect(Image1.Canvas.ClipRect);

bitmap2.Height := bitmap1.Height;

bitmap2.Width := bitmap1.Width;



for y := 0 to bitmap2.Height - 1 do begin

ptr := bitmap1.ScanLine[y];

newscanline := bitmap2.ScanLine[((bitmap1.Height - 1) - y)];

for x := 0 to bitmap1.Width - 1 do begin

newscanline[x] := ptr[x];

end;

end;



Image1.Canvas.Draw(0,0,bitmap2);

end;

First I do a cleanup of my display area. I use the ClipRect as it is just the dirty area, the area that have been alreay drawn on, no need to refresh the whole image canvas. Next, I have to define the size of my work area (bitmap2). You will notice that there are two for loops next. In the outer for loop, I start at the top of bitmap1 and work my way down and start at the bottom of bitmap2 and work my way up. This gives me the effect that I want: it flips the image. All the inner for loop does is copy each element of the ScanLine from bitmap1 to the ScanLine of bitmap2. All the is left to do is display bitmap2. I could achieve a mirror image instead of a flip with a small change in the ScanLine logic:

for y := 0 to bitmap2.Height - 1 do begin

ptr := bitmap1.ScanLine[y];

newscanline := bitmap2.ScanLine[y];

for x := 0 to bitmap1.Width - 1 do begin

newscanline[((bitmap1.Width - 1) - x)] := ptr[x];

end;

end;

Now lets look at the code to rotate the bitmap:

procedure TForm1.Button3Click(Sender: TObject);

var

y: integer;

x: integer;

begin

Image1.Canvas.FillRect(Image1.Canvas.ClipRect);

bitmap2.Height := bitmap1.Width;

bitmap2.Width := bitmap1.Height;



for y := 0 to bitmap1.Width - 1 do begin

newscanline := bitmap2.ScanLine[y];

for x := 0 to bitmap1.Height - 1 do begin

ptr := bitmap1.ScanLine[x];

newscanline[x] := ptr[y];

end;

end;

Image1.Canvas.Draw(0,0,bitmap2);

end;

The loop logic here has to be different because you have to write the ScanLine of bitmap1 into a specific location in all the ScanLines of bitmap2. If you take a close look at the preceding code, that is exactly what I am doing. With the same type of logic that we used to flip in the previous code, the preceding code could be modified to rotate and mirror the image. But, I will leave that up to you to implement. I do not want to have all the fun.


 
啊~~~~~~魂飞魄散!
有没有搞错!这么麻烦!
 
32bit深度历险新放上一个构件,以下是描述:
PPROTIMAGE.ZIP

TRotBitmap 是改良版的 TBitmap 类,能够顺时钟或逆时钟旋转
.BMP 图像文件 90、180、270 等角度 ( 1.0 版,附源码 ),作者
: Pavel Petsevich。

不知道满不满足你的要求,我已经下载,大约200k,
如果你下载有困难, 我可以发给你,我的邮箱是
kundeng@email.com.cn
 
90、180、270 这样的再加上反转都是两句话的事,不需要做控件吧
要是是任意角度,我在画pixel是要是用了round 来取整,总是有些
pixel画不到,怎么做啊???
 
接受答案了.
 
后退
顶部