会员: 密码:  免费注册 | 忘记密码 | 会员登录 网页功能: 加入收藏 设为首页 网站搜索  
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
  · 杀毒专区
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
技术文档 > Delphi
基本图象处理代码(1)
发表日期:2003-03-07 00:00:00作者:e 出处:  

[图像的旋转和翻转]

以下代码用ScanLine配合指针移动实现,用于24位色,至于其它色深的处理和有些代码为什么要这样写的问题可查看我的另一篇文章!

//旋转90度

procedure Rotate90(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Height;

 Bmp.Height := Bitmap.Width;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for j := 0 to Height do

 begin

  rowIn := Bitmap.ScanLine[j];

  for i := 0 to Width do

  begin

   rowOut := Bmp.ScanLine[i];

   Inc(rowOut,Height - j);

   rowOut^ := rowIn^;

   Inc(rowIn);

  end;

 end;

 Bitmap.Assign(Bmp);

end;

//旋转180度

procedure Rotate180(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Width;

 Bmp.Height := Bitmap.Height;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for j := 0 to Height do

 begin

  rowIn := Bitmap.ScanLine[j];

  for i := 0 to Width do

  begin

   rowOut := Bmp.ScanLine[Height - j];

   Inc(rowOut,Width - i);

   rowOut^ := rowIn^;

   Inc(rowIn);

  end;

 end;

 Bitmap.Assign(Bmp);

end;

//旋转270度

procedure Rotate270(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Height;

 Bmp.Height := Bitmap.Width;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for j := 0 to Height do

 begin

  rowIn := Bitmap.ScanLine[j];

  for i := 0 to Width do

  begin

   rowOut := Bmp.ScanLine[Width - i];

   Inc(rowOut,j);

   rowOut^ := rowIn^;

   Inc(rowIn);

  end;

 end;

 Bitmap.Assign(Bmp);

end;

任意角度旋转就是将原图上的像素映射到新图上,以下代码为了好理解,并未进行充分优化!但速度上已经比较快了!我的另一篇文章中对优化问题进行了些简单说明,也就是尽量少用浮点运算!

前面为判断部分,如果是90,180,270这类特殊角度,将调用上面的代码,这样效率更高!

//任意角度

function RotateBitmap(Bitmap:TBitmap;Angle:Integer;BackColor:TColor):TBitmap;

var

 i,j,iOriginal,jOriginal,CosPoint,SinPoint : integer;

 RowOriginal,RowRotated : pRGBTriple;

 SinTheta,CosTheta : Extended;

 AngleAdd : integer;

begin

 Result:=TBitmap.Create;

 Result.PixelFormat := pf24bit;

 Result.Canvas.Brush.Color:=BackColor;

 Angle:=Angle Mod 360;

 if Angle<0 then Angle:=360-Abs(Angle);

 if Angle=0 then

  Result.Assign(Bitmap)

 else if Angle=90 then

 begin

  Result.Assign(Bitmap);

  Rotate90(Result);//如果是旋转90度,直接调用上面的代码

 end

 else if (Angle>90) and (Angle<180) then

 begin

  AngleAdd:=90;

  Angle:=Angle-AngleAdd;

 end

 else if Angle=180 then

 begin

  Result.Assign(Bitmap);

  Rotate180(Result);//如果是旋转180度,直接调用上面的过程

 end

 else if (Angle>180) and (Angle<270) then

 begin

  AngleAdd:=180;

  Angle:=Angle-AngleAdd;

 end

 else if Angle=270 then

 begin

  Result.Assign(Bitmap);

  Rotate270(Result);//如果是旋转270度,直接调用上面的过程

 end

 else if (Angle>270) and (Angle<360) then

 begin

  AngleAdd:=270;

  Angle:=Angle-AngleAdd;

 end

 else

  AngleAdd:=0;

 if (Angle>0) and (Angle<90) then

 begin

 SinCos((Angle + AngleAdd) * Pi / 180, SinTheta, CosTheta);

 if (SinTheta * CosTheta) < 0 then

 begin

  Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta));

  Result.Height := Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta));

 end

 else

 begin

  Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta));

  Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta));

 end;

 CosTheta:=Abs(CosTheta);

 SinTheta:=Abs(SinTheta);

 if (AngleAdd=0) or (AngleAdd=180) then

 begin

  CosPoint:=Round(Bitmap.Height*CosTheta);

  SinPoint:=Round(Bitmap.Height*SinTheta);

 end

 else

 begin

  SinPoint:=Round(Bitmap.Width*CosTheta);

  CosPoint:=Round(Bitmap.Width*SinTheta);

 end;

 for j := 0 to Result.Height-1 do

 begin

  RowRotated := Result.Scanline[j];

  for i := 0 to Result.Width-1 do

  begin

   Case AngleAdd of

    0:

    begin

     jOriginal := Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta)-1;

     iOriginal := Round((i+1)*CosTheta-(CosPoint-j-1)*SinTheta)-1;

    end;

    90:

    begin

     iOriginal := Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta)-1;

     jOriginal := Bitmap.Height-Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta);

    end;

    180:

    begin

     jOriginal := Bitmap.Height-Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta);

     iOriginal := Bitmap.Width-Round((i+1)*CosTheta-(CosPoint-j-1)*SinTheta);

    end;

    270:

    begin

     iOriginal := Bitmap.Width-Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta);

     jOriginal := Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta)-1;

    end;

   end;

   if (iOriginal >= 0) and (iOriginal <= Bitmap.Width-1)and

     (jOriginal >= 0) and (jOriginal <= Bitmap.Height-1)

   then

   begin

    RowOriginal := Bitmap.Scanline[jOriginal];

    Inc(RowOriginal,iOriginal);

    RowRotated^ := RowOriginal^;

    Inc(RowRotated);

   end

   else

   begin

    Inc(RowRotated);

   end;

  end;

 end;

 end;

end;

虽然这已经实现了图像任意角度的旋转,但注意看看上面的代码,都是用Round取整,也就是在原图中找最近的像素填充到新图中,这样在边缘会产生锯齿!如果想效果更好,应该是用四个像素的值运算后得到新像素的值!

如对应到原图的坐标是(6.3,8.6),用第一种方法可能就用(6,9)填充了该像素,但如果想消除边缘锯齿,就应该用(6,8)、(6,9)、(7,8)、(7,9)运算得出新点的像素,而边缘就用颜色等于背景色的点代替!

感兴趣的朋友可以找些二次线性插值资料看看,或者以后再讨论,这里就不多说了!

后面的浮雕滤镜效果其实就用到了线性插值的思想!

//水平翻转

procedure FlipHorz(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Width;

 Bmp.Height := Bitmap.Height;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for j := 0 to Height do

 begin

  rowIn := Bitmap.ScanLine[j];

  for i := 0 to Width do

  begin

   rowOut := Bmp.ScanLine[j];

   Inc(rowOut,Width - i);

   rowOut^ := rowIn^;

   Inc(rowIn);

  end;

 end;

 Bitmap.Assign(Bmp);

end;

//垂直翻转

procedure FlipVert(const Bitmap:TBitmap);

var

 i,j:Integer;

 rowIn,rowOut:pRGBTriple;

 Bmp:TBitmap;

 Width,Height:Integer;

begin

 Bmp:=TBitmap.Create;

 Bmp.Width := Bitmap.Height;

 Bmp.Height := Bitmap.Width;

 Bmp.PixelFormat := pf24bit;

 Width:=Bitmap.Width-1;

 Height:=Bitmap.Height-1;

 for j := 0 to Height do

 begin

  rowIn := Bitmap.ScanLine[j];

  for i := 0 to Width do

  begin

   rowOut := Bmp.ScanLine[Height - j];

   Inc(rowOut,i);

   rowOut^ := rowIn^;

   Inc(rowIn);

  end;

 end;

 Bitmap.Assign(Bmp);

end;

其实旋转90、180、270度,水平垂直翻转的原理基本类似,所以也可以改写为一个过程!

如果灵活的使用指针,减少用ScanLine的次数,代码效率还能有所提升~~~

返回顶部】 【打印本页】 【关闭窗口

关于我们 / 给我留言 / 版权举报 / 意见建议 / 网站编程QQ群   
Copyright ©2003- 2024 Lihuasoft.net webmaster(at)lihuasoft.net 加载时间 0.00176