DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: fhc2004
今日帖子: 12
在线用户: 20
导航: 论坛 -> 论坛精华贴 斑竹: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 (阿门)
----------------------------------------------
-
作者:
男 pengle (pengle) ★☆☆☆☆ -
普通会员
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楼是对的!
此帖子包含附件:
JPEG 图像
大小: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楼: 多谢各位提示,我已经从大富翁论坛中收集了一些资料,正在整理和试用。
再次谢谢。
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行121.0938毫秒 RSS