想知道Bmp图像的缩小放大用Tcanvas.StretchDraw还是用StretchBlt函数?(50分)

  • 主题发起人 jialiang
  • 开始时间
J

jialiang

Unregistered / Unconfirmed
GUEST, unregistred user!
TCanvas的StretchDraw定义如下:
procedure TCanvas.StretchDraw(const Rect: TRect; Graphic: TGraphic);
begin
if Graphic <> nil then
begin
Changing;
RequiredState(csAllValid);
Graphic.Draw(Self, Rect);
Changed;
end;
end;

看样子是不是用了TGraphic的Draw方法,其定义如下:
procedure Draw(ACanvas: TCanvas; const Rect: TRect); virtual; abstract;

Abstract抽象定义,是继承它的父类TPersitent的Draw吗?还是可是自己定义?
查看了TPersistent的类,无Draw声明,是留给用户定义?
查来查去还是不知TCanvas.StretchDraw具体实现如何,
也不知同StretchBlt,哪个更好些,哪位讲一下,并讲讲这StretchDraw实现。

以上50分,还有如果哪位大侠有BMP、JPG转ICO的源码(效果当然要好了)可以200分交换。


 
TCanvas.StretchDraw 应该是调用 StretchBlt API的(我没有看VCL源码,纯粹估计),
当然直接调用StretchBlt API 快一点啦。

var
MyJpeg: TJpegImage;
bmp: Tbitmap;
begin
bmp:=tbitmap.Create;
MyJpeg:= TJpegImage.Create;
myjpeg.LoadFromFile('c:/windows/desktop/aa.jpg');
bmp.Assign(myjpeg);
bmp.SaveToFile('c:/windows/desktop/test.bmp'); // Save the JPEG to Disk
end;


procedure Bmp2Ico(bmp, ico: string); //bmp和ico是文件名
var
IconSizeX : integer;
IconSizeY : integer;
myBmp : TBitmap;
AndMask : TBitmap;
XOrMask : TBitmap;
IconInfo : TIconInfo;
Icon : TIcon;
begin
IconSizeX := GetSystemMetrics(SM_CXICON);
IconSizeY := GetSystemMetrics(SM_CYICON);

myBmp := TBitmap.Create;
myBmp.LoadFromFile(bmp);

AndMask := TBitmap.Create;
AndMask.Width := IconSizeX;
AndMask.Height := IconSizeY;
AndMask.Canvas.Brush.Color := clBlack;
AndMask.Canvas.Rectangle(0, 0, IconSizeX, IconSizeY);

XOrMask := TBitmap.Create;
XOrMask.Width := IconSizeX;
XOrMask.Height := IconSizeY;
StretchBlt(XorMask.Canvas.Handle, 0, 0, IconSizeX, IconSizeY,
myBmp.Canvas.Handle, 0, 0, myBmp.Width, myBmp.Height, SRCCOPY);

Icon := TIcon.Create;
IconInfo.fIcon := true;
IconInfo.xHotspot := 0;
IconInfo.yHotspot := 0;
IconInfo.hbmMask := AndMask.Handle;
IconInfo.hbmColor := XOrMask.Handle;
Icon.Handle := CreateIconIndirect(IconInfo);

AndMask.Free;
XOrMask.Free;
myBmp.Free;

Icon.SaveToFile(ico);
Icon.Free;
end;
 
用Tcanvas.StretchDraw可以实现图象的放大放小。
用TCanvas.CopyRect也可以。
你也许对对象的多态性了解不清楚。
你传入的参数Graphic必须为一个具体的TGraphic对象(TGraphic派生类的如TImage类
的一个实例!),而这个具体的对象已经实现了祖先类的抽象方法。

     ----好久没来DWF了!


The following example is taken from the custom draw demo. It shows how the OnCustomDraw event handler draws the background for the tree view before the items and lines are drawn.

procedure TCustomDrawForm.TVCustomDraw(Sender: TCustomTreeView; const ARect: TRect; var DefaultDraw: Boolean);
begin
//This event should be used to draw any background colors or images.
//ARect represents the entire client area of the TreeView.
//Use the TreeView's canvas to do the drawing.
//Note that drawing a background bitmap is not really supported by CustomDraw,
//so scrolling can get messy. Best to subclass the TreeView and handle scrolling

//messages.
with TV.Canvas do
begin
if None1.Checked then //no picture
begin
Brush.Color := BkgColorDialog.Color;
Brush.Style := FBrushStyle;
FillRect(ARect);
end else
if Tile1.Checked then //tile bitmap
begin
Brush.Bitmap := Image1.Picture.Bitmap;
FillRect(ARect);
end else //Stretch across the canvas.

StretchDraw(ARect, Image1.Picture.Bitmap);
end;
DefaultDraw := FDefaultDraw;
//setting DefaultDraw to false here prevents all calls to OnCustomDrawItem.
end;

 
多谢二位,能给个StretchBlt的实例吗,
刚才看了一个帖子说StretchBlt有Bug,我不知道我现在的实现是语句问题还是Bug 问题,
语句如下:
SetStretchBltMode(desBitmap.Handle,HALFTONE);
StretchBlt(desBitmap.Handle,0,0,Width,Height,srcBitmap.Handle,0,0,srcBitmap.Width,
srcBitmap.Height,Blackness);
结果是生成的小图片是白色的(80*80,在2000Server下)。
DragonPC_???:
转图标的己找了个很好的控件,多谢了,分分少不了你的。
再帮我看看这问题:http://www.delphibbs.com/delphibbs/dispq.asp?lid=689552
我的分全压在上面了。


 
做出来了,
StretchBlt(desBitmap.Canvas.Handle,AWidthOffset,AHeightOffset,AWidth+AWidthOffset,AHeight+AHeightOffset,srcBitmap.Canvas.Handle,
0,0,srcBitmap.Width,srcBitmap.Height,SrcCopy);

就是Stretchblt的效果太差劲了,根本不能同StretchDraw比,
还是我的方法不对,哪位有好点的算法。
 
你要先清空图片框,再调用StretchBlt函数,另外注意缩放到内存镜像的设备句柄上,
而非直接到位图句柄上,这样速度会有很大的提高。
 
YB__unique:
有没有这类的例子程序?
 
多人接受答案了。
 
顶部