+ -
当前位置:首页 → 问答吧 → 初次接触GDI+,做了一个工具函数库。抛砖引玉,公开源码,请大家看看这个思路对不对,以及实现的方法是不是高效

初次接触GDI+,做了一个工具函数库。抛砖引玉,公开源码,请大家看看这个思路对不对,以及实现的方法是不是高效

时间:2011-10-08

来源:互联网

以前做过一个批量缩小照片的工具,因为标准canvas的缩小效果太差,具体的缩小是利用cximage(vc编译的外部程序)实现的
后来做一个照片-标签管理工具(觉得google的picasa的标签太不够用了,它的人脸自动识别倒不错。这个工具支持树形层次的任意多、任意层的标签),也需要把照片缩略显示以便选择、查看
国庆时做拼图工具,也需要把原图缩放成界面大小,同时还需要随意割取区域显示到另一个区域,所以,标准canvas又不够用了
所以终于留意到gdi+了

开始以为程序uses gdiplus后,原来标准的canvas的方法就能自动拥有gdi+的效果了
结果,不是这样的。。。。。

于是转为希望仅仅在需要较好处理效果的地方能利用gdi+,
最需要的地方自然是:
1、能加载任意格式的图形文件(本来只能加载bmp/icon/wmf等格式,users jpeg后能加载jpg了,但是gif/png。。。呢)
2、图像的缩放,标准canvas的效果是很差的,gdi+则包含了效果不错的处理算法
3、图像的旋转、对称翻转(jpeg好像只是文件头有对应的标志,而不用真正重新处理整个图像[未确定])

目前只实现了1、2,抛砖引玉,公开源码,请大家看看这个思路对不对,以及实现的方法是不是高效(有没有迂回、冗余了):

Delphi(Pascal) code
unit unitGdiPlus;

interface

uses classes,Graphics,ExtCtrls,types;

function BmpClientRect(bmp:TBitmap):types.Trect; //取bmp的大小到rect,相当于Timage.clientrect
function RectWidth(r:types.Trect):Integer;   //取rect的宽度,仅仅减少代码
function RectHeight(r:types.Trect):Integer;  //取rect的高度,仅仅减少代码

function BmpLoad(bmp:TBitmap;fn:String):Boolean; //把图形文件fn加载到bmp。使用gdi+就可以支持jpg/gif/png等多种图形文件了
function bmpCopy(bmpf,bmpt:Tbitmap;rectf,rectt:types.Trect):Boolean; overload;
//把bmpf的rectf区域复制到bmpt的rectt区域,功能与标准的canvas.copyrect一样,只是因为后者的缩放效果太差
function bmpCopy(bmpf,bmpt:Tbitmap):Boolean; overload;
//把bmpf的全部复制到bmpt的全部区域,功能与标准的canvas.copyrect一样,只是因为后者的缩放效果太差

function BmpLoadRect(bmp:TBitmap;fn:String;p100:Integer=100):Boolean; overload;
//把图形文件fn加载到bmp,按p100/100的比例设置bmp的大小
function BmpLoadRect(bmp:TBitmap;fn:String;p100:Integer;var w,h:Integer):Boolean; overload;
//把图形文件fn加载到bmp,按p100/100的比例设置bmp的大小,同时取得图形文件的原始长宽到w,h
function BmpLoadRect(bmp:TBitmap;fn:String;r:types.Trect;bScale:Boolean):Boolean; overload;
//把图形文件fn加载到bmp的r区域,bScale决定是否保持图形文件的原始长宽比例,否则填满r区域
function BmpLoadRect(bmp:TBitmap;fn:String;r:types.Trect;bScale:Boolean;var w,h:Integer):Boolean; overload;
//把图形文件fn加载到bmp的r区域,bScale决定是否保持图形文件的原始长宽比例,否则填满r区域。同时取得图形文件的原始长宽到w,h

implementation

uses SysUtils,Gdiplus;

function RectWidth(r:types.Trect):Integer;
Begin
  result:=r.Right-r.Left+1;
End;
function RectHeight(r:types.Trect):Integer;
Begin
  result:=r.Bottom-r.Top+1;
End;

function BmpClientRect(bmp:TBitmap):types.Trect;
Begin
  Result.Left:=0;
  Result.Top:=0;
  Result.Right:=bmp.Width-1;
  Result.Bottom:=bmp.Height-1;
End;

function BmpLoad(bmp:TBitmap;fn:String):Boolean;
var
  i:Gdiplus.Tgpbitmap;
begin
  Result:=false;
  if not fileexists(fn) then
    Exit;
  try
  i:=Gdiplus.Tgpbitmap.Create(fn);
  try
  bmp.Handle:=i.GetHBITMAP(0);
  except
  end;
  i.Free;
  Result:=true;
  except
  end;
end;

function bmpCopy(bmpf,bmpt:Tbitmap;rectf,rectt:types.Trect):Boolean;
var
  t:TBitmap;
  gf,gt:TgpBitmap;
  g:TGpGraphics;
begin
  result:=false;
  if (bmpf.Handle=0) or (bmpt.Handle=0) then
    exit;

  if (rectwidth(rectf)=rectwidth(rectt))
   and (rectheight(rectf)=rectheight(rectt)) then
  Begin
    bmpt.Canvas.CopyRect(rectt,bmpf.Canvas,rectf);
    result:=True;
    exit;
  End;

  t:=TBitmap.Create;
  t.Width:=rectwidth(rectf);
  t.Height:=rectheight(rectf);
  t.Canvas.CopyRect(BmpClientRect(t),bmpf.Canvas,rectf);
  gf:=TGpBitmap.Create(t.Handle,t.Palette);
  t.Free;
  gt:=TGpBitmap.Create(bmpt.Handle,bmpt.Palette);
  g:=TGpGraphics.Create(gt);
  g.DrawImage(gf,rectt.Left,rectt.Top,rectwidth(rectt),rectheight(rectt));
  bmpt.Handle:=gt.GetHBITMAP(0);
  gt.Free;
  gf.Free;
  g.Free;
  result:=True;
end;
function bmpCopy(bmpf,bmpt:Tbitmap):Boolean; overload;
var
  gf,gt:TgpBitmap;
  g:TGpGraphics;
begin
  result:=false;
  if (bmpf.Handle=0) or (bmpt.Handle=0) then
    exit;
  gf:=TGpBitmap.Create(bmpf.Handle,bmpf.Palette);
  gt:=TGpBitmap.Create(bmpt.Handle,bmpt.Palette);
  g:=TGpGraphics.Create(gt);
  g.DrawImage(gf,0,0,bmpt.Width,bmpt.Height);
  bmpt.Handle:=gt.GetHBITMAP(0);
  gt.Free;
  gf.Free;
  g.Free;
  result:=True;
End;

function BmpLoadRect(bmp:TBitmap;fn:String;p100:Integer;var w,h:Integer):Boolean; overload;
var
  gf,gt:TgpBitmap;
  g:TGpGraphics;
begin
  Result:=false;
  if not fileexists(fn) then
    Exit;
  gf:=Gdiplus.Tgpbitmap.Create(fn);
  w:=gf.Width;
  h:=gf.Height;
  if (p100<=0) and (bmp.Handle=0) or (p100=100) then
  Begin
    bmp.Handle:=gf.GetHBITMAP(0);
    gf.Free;
    Result:=true;
    exit;
  End;
  bmp.Width:=gf.Width*p100 div 100;
  bmp.Height:=gf.Height*p100 div 100;
  gt:=TGpBitmap.Create(bmp.Handle,bmp.Palette);
  g:=TGpGraphics.Create(gt);
  if (p100<=0) then
    g.DrawImage(gf,0,0,bmp.Width,bmp.Height)
  else
    g.DrawImage(gf,0,0,gf.Width*p100 div 100,gf.Height*p100 div 100);
  bmp.Handle:=gt.GetHBITMAP(0);
  gt.Free;
  gf.Free;
  g.Free;
  Result:=true;
end;
function BmpLoadRect(bmp:TBitmap;fn:String;p100:Integer=100):Boolean;
var
  w,h:Integer;
Begin
  Result:=BmpLoadRect(bmp,fn,p100,w,h);
End;
function BmpLoadRect(bmp:TBitmap;fn:String;r:types.Trect;bScale:Boolean;var w,h:Integer):Boolean; overload;
var
  gf,gt:TgpBitmap;
  g:TGpGraphics;
  procedure rerect();
  var
    w,h, rw,rh:Integer;
  begin
    rw:=RectWidth(r);
    rh:=RectHeight(r);
    Begin
      w:=(gf.Width)*rh div gf.height;
      if (w<=rw) then
      Begin
        w:=(rw-w) div 2;
        Inc(r.Left,w);
        dec(r.Right,w);
      End
      else
      Begin
        h:=(gf.Height)*rw  div gf.Width;
        h:=(rh-h) div 2;
        Inc(r.Top,h);
        dec(r.Bottom,h);
      End;
    End;

  end;
begin
  Result:=false;
  if not fileexists(fn) then
    Exit;
  gf:=Gdiplus.Tgpbitmap.Create(fn);
  w:=gf.Width;
  h:=gf.Height;
  gt:=TGpBitmap.Create(bmp.Handle,bmp.Palette);
  g:=TGpGraphics.Create(gt);
  if bScale then
    reRect();
  g.DrawImage(gf,r.Left,r.Top,rectwidth(r),rectheight(r));
  bmp.Handle:=gt.GetHBITMAP(0);
  gt.Free;
  gf.Free;
  g.Free;
  Result:=true;
end;
function BmpLoadRect(bmp:TBitmap;fn:String;r:types.Trect;bScale:Boolean):Boolean;
var
  w,h:Integer;
Begin
  Result:=BmpLoadRect(bmp,fn,r,bscale,w,h);
End;

end.

作者: sz_haitao   发布时间: 2011-10-08

沙发,学习

作者: onlyou13   发布时间: 2011-10-08

谢谢,无私奉献。

作者: Terony   发布时间: 2011-10-08

学习,感谢....

作者: dongmei757   发布时间: 2011-10-08