导航:
论坛 -> 论坛精华贴
斑竹:liumazi,iamdream
作者:
bear (bear)
★☆☆☆☆
-
盒子活跃会员
2003/9/3 9:38:59
标题:
如何将一个BMP生成旋转了90度的另一个BMP
浏览:4359
加入我的收藏
楼主:
请各位高手帮忙 我想将多个 BMP 文件转换为旋转了 90 度的新 BMP 文件, 请问如何编程。
----------------------------------------------
-
作者:
zizii (高高高级馒头)
★☆☆☆☆
-
神秘会员
2003/9/3 16:10:09
1楼:
bit[x,y]到bit[y,x]的操作。
----------------------------------------------
维护世界和平,共创美好盒子。
作者:
bear (bear)
★☆☆☆☆
-
盒子活跃会员
2003/9/4 9:26:28
2楼:
谢谢 zizii 的提示。 能否给个类似的例子。
----------------------------------------------
-
作者:
zizii (高高高级馒头)
★☆☆☆☆
-
神秘会员
2003/9/4 12:55:39
3楼:
我手头没有这样的例子,你找找控件看有没有这样的代码。
----------------------------------------------
维护世界和平,共创美好盒子。
作者:
boy (阿門)
★☆☆☆☆
-
盒子活跃会员
2003/9/4 15:04:21
4楼:
Image 任意角度的旋轉 兔老(轉)發布於:2001-07-11 09:29:23 調用方法: bmp_rotate(Image1.Picture.Bitmap, Image2.Picture.Bitmap, RAngle); procedure TfrmColor.bmp_rotate(src,dst:tbitmap;angle:extended); var c1x,c1y,c2x,c2y:integer; p1x,p1y,p2x,p2y:integer; radius,n:integer; alpha:extended; c0,c1,c2,c3:tcolor; begin //將角度轉換為PI值 angle := (angle / 180) * pi; // 計算中心點,你可以修改它 c1x := src.width div 2; c1y := src.height div 2; c2x := dst.width div 2; c2y := dst.height div 2; // 步驟數值number if c2x < c2y then n := c2y else n := c2x; dec (n,1); // 開始旋轉 for p2x := 0 to n do begin for p2y := 0 to n do begin if p2x = 0 then alpha:= pi/2 else alpha := arctan2(p2y,p2x); radius := round(sqrt((p2x*p2x)+(p2y*p2y))); p1x := round(radius * cos(angle+alpha)); p1y := round(radius * sin(angle+alpha)); c0 := src.canvas.pixels[c1x+p1x,c1y+p1y]; c1 := src.canvas.pixels[c1x-p1x,c1y-p1y]; c2 := src.canvas.pixels[c1x+p1y,c1y-p1x]; c3 := src.canvas.pixels[c1x-p1y,c1y+p1x]; dst.canvas.pixels[c2x+p2x,c2y+p2y]:=c0; dst.canvas.pixels[c2x-p2x,c2y-p2y]:=c1; dst.canvas.pixels[c2x+p2y,c2y-p2x]:=c2; dst.canvas.pixels[c2x-p2y,c2y+p2x]:=c3; end; application.processmessages end; end; *************8 ----把一個點繞原點旋轉嶠嵌群螅 碌淖虃虷鼽m與原坐標位置雛 關繫是: X=x cos幔 sin? Y=x sin幔 cos? 例如要把位圖順時針旋轉90度,坐標變換公式為:X=-yY=x ----把這一公式用到Image構件上,顯示位圖的主要問題是Image構 件顯示的位圖隻有一個像限,並且x、y坐標也是互相顛倒的,為了 解決這個問題,必須在Image構件上建立一個新的坐標原點。下面就 舉例說明。 ----1.新建一工程project1,在form1上添加image1、image2、 image3、image4,其Autosize屬性設為True,image1用來顯示原 圖,image2、image3、image4分別用來顯示旋轉90度、180度和270 度後的圖像。雙擊image1,選定一幅bmp圖。 ----2.添加Button1、Button2、Button3和Button4按鈕,其 caption屬性分別為"原圖"、"旋轉90度"、"旋轉180度"、 "旋轉270度"。 ----3.編寫"旋轉90度"按鈕的OnClick事件。 procedureTForm1.Button2Click(Sender:TObject); var i,j:integer; begin //確定旋轉後位圖的大小 image2.Picture.Bitmap.Height:=image1.picture.width; image2.Picture.Bitmap.Width:=image1.picture.height; fori:=0toimage1.Heightdo forj:=0toimage1.Widthdo image2.canvas.Pixels[(-i+image1.Height), j]:=image1.canvas.Pixels[j,i]; end; ----4.編寫"旋轉180度"按鈕的OnClick事件。 procedureTForm1.Button3Click(Sender:TObject); var i,j:integer; begin //確定旋轉後位圖的大小 image3.Picture.Bitmap.Height:=image1.picture.Height; image3.Picture.Bitmap.Width:=image1.picture.Width; fori:=0toimage1.Heightdo forj:=0toimage1.Widthdo image3.canvas.Pixels[(image1.Width -j),(image1.Height-i)]:=image1.canvas.Pixels[j,i]; end; ----5.編寫"旋轉270度"按鈕的OnClick事件。代碼和步驟3相 似,隻需要用image4替換image2,然後用以下的語句替換步驟3for 循環中的原有的語句。 image4.canvas.Pixels[i,(image1.Width-j)]:=image1.canvas.Pixels[j,i]; procedure Rotate(Bmp,Dst:TFastRGB;cx,cy:Integer;Angle:Extended); var cAngle, sAngle: Double; xDiff, yDiff, xpr,ypr, ix,iy, px,py, x,y: Integer; Tmp: PFColor;{what means?} begin Angle:=-Angle*Pi/180; sAngle:=Sin(Angle); cAngle:=Cos(Angle); xDiff:=(Dst.Width-Bmp.Width)div 2; yDiff:=(Dst.Height-Bmp.Height)div 2; Tmp:=Dst.Bits;{what means?} for y:=0 to Dst.Height-1 do begin py:=2*(y-cy)+1; for x:=0 to Dst.Width-1 do begin px:=2*(x-cx)+1; xpr:=Round(px*cAngle-py*sAngle); ypr:=Round(px*sAngle+py*cAngle); ix:=((xpr-1)div 2+cx)-xDiff; iy:=((ypr-1)div 2+cy)-yDiff; if(ix>-1)and(ix<Bmp.Width)and(iy>-1)and(iy<Bmp.Height)then Tmp^:=Bmp.Pixels[iy,ix]; {what means?} Inc(Tmp); end; Tmp:=Pointer(Integer(Tmp)+Dst.Gap); {what means?} end; end; 原理: cos(Alpha), sin(Alpha), 0 隻需要用源矩陣乘以 -sin(Alpha),cos(Alpha), 0 0, 0, 1 如果你發現轉過來的圖形帶有很整齊的花點,解決的辦法是反向計算,即從目標求的源點的坐標和像素值。 以上的例子就是這樣的。 如果真的按下面下矩陣計算每個點,目標區有一些點會是白點(因為有些源點通過計算和四舍五入在目標中湊到一起了),我以前解決的辦法是從目標求的源點的坐標和像素值,不過首先要取到目標區的區域(往往是斜的)。 cos(Alpha), sin(Alpha), 0 -sin(Alpha),cos(Alpha), 0 0, 0, 1 下載我說的控件嗎,有現成的例子及DEMO! http://www.crosswinds.net/~khojasteh/delphi-components.html TRotateImage v1.21 This component is a visual component similar to TImage with ability to rotate the image in any arbitrary angle. TRotateImage can be used on Delphi 3, 4, and 5.
----------------------------------------------
Delphi開發◆伺服器架設◆免安裝APACHE,PHP,CGI Perl, MYSQL ★
作者:
bear (bear)
★☆☆☆☆
-
盒子活跃会员
2003/9/5 9:01:49
5楼:
十分感谢 boy (阿门)
----------------------------------------------
-
作者:
2003/10/15 16:13:43
6楼:
上面的速度太慢。小图片倒无所谓。大图片就不行了。 请用scanline函数
----------------------------------------------
-
作者:
bios (阿贡)
★☆☆☆☆
-
盒子中级会员
2004/1/13 18:28:06
7楼:
同意6楼!
----------------------------------------------
作者:
bear (bear)
★☆☆☆☆
-
盒子活跃会员
2004/1/20 8:00:30
8楼:
总结了一下,现在将旋转90度、180度和270度的例程列后: 1、旋转90° procedure TForm1.Rotate90(Img,Img2:TImage); var i,j:integer; begin Img2.Height:=Img.picture.width; //确定旋转后位图的大小 Img2.Width:=Img.picture.height; for i:=0 to Img.Height do //计算旋转后的坐标 for j:=0 to Img.Width do Img2.canvas.Pixels[(Img.Height-i), j]:=Img.canvas.Pixels[j,i]; end; 2、旋转180° procedure TForm1.Rotate180(Img,Img2:TImage); var i,j:integer; begin Img2.Height:=Img.picture.height; Img2.Width:=Img.picture.width; for i:=0 to Img.Height do for j:=0 to Img.Width do Img2.canvas.Pixels[(Img.Width-j),(Img.Height-i)]:=Img.canvas.Pixels[j,i]; end; 3、旋转270° procedure TForm1.Rotate270(Img,Img2:TImage); var i,j:integer; begin Img2.Height:=Img.picture.width; Img2.Width:=Img.picture.height; for i:=0 to Img.Height do for j:=0 to Img.Width do Img2.canvas.Pixels[i,(Img.Width-j)]:=Img.canvas.Pixels[j,i]; end;
----------------------------------------------
-
作者:
bios (阿贡)
★☆☆☆☆
-
盒子中级会员
2004/1/21 8:33:28
9楼:
8楼的方法 已经被偶否认了 因为偶发现有些图片用此法是行不通的! 不信算了! 还是6楼是对的!
此帖子包含附件: 大小: 16.7K
----------------------------------------------
作者:
bear (bear)
★☆☆☆☆
-
盒子活跃会员
2004/1/22 14:54:01
10楼:
bios: 继续请教这个问题。我参考scanline的帮助,编制了一个过程,但结果没有达到目的。请指出错在什么地方。谢谢。 以下过程想将位图旋转90度,但没有达到目的。也曾按 ScanLine 帮助的示例,定义 P:PByteArray;,也没有达到目的。 procedure TForm1.Button2Click(Sender: TObject); var x,y: Integer; OrgBmp,RtnBmp: TBitMap; P:PWordArray; begin OrgBmp := TBitMap.create; RtnBmp := TBitMap.create; try OrgBmp.LoadFromFile ('C:\Program Files\Common Files\Borland Shared\Images\Splash\256color\HANDSHAK.BMP'); RtnBmp.Height:=OrgBmp.width; RtnBmp.Width:=OrgBmp.height; for y:=0 to OrgBmp.Height-1 do begin P:= OrgBmp.ScanLine[y]; for x := 0 to OrgBmp.Width -1 do RtnBmp.canvas.Pixels[(OrgBmp.Height-y), x]:=P[x] end; Canvas.Draw(0,0,RtnBmp); finally OrgBmp.Free; RtnBmp.Free; end; end;
----------------------------------------------
-
作者:
bear (bear)
★☆☆☆☆
-
盒子活跃会员
2004/1/25 8:02:28
11楼:
多谢各位提示,我已经从大富翁论坛中收集了一些资料,正在整理和试用。 再次谢谢。
----------------------------------------------
-