如何能实现图像的放大缩小? ( 积分: 200 )

  • 主题发起人 主题发起人 popoaleck
  • 开始时间 开始时间
P

popoaleck

Unregistered / Unconfirmed
GUEST, unregistred user!
我在PaintBox上画了一些夭量图形,现在想实现将图形放大及缩小的功能(类似于放大镜那样的效果),应该怎样做? 请高手提供些思路.
 
用StretchBlt函数
 
用这个TCanvas中的函数
procedure StretchDraw(const Rect: TRect; Graphic: TGraphic);
 
下面这个例子,截屏,缩小,显示

var
bmp:tbitmap;
DC:hdc;
begin
bmp:=tbitmap.Create;
with bmp do
begin
PixelFormat:=pf24bit;
Width:=screen.Width shr 2;
Height:=screen.Height shr 2;
dc:=getdc(0);
SetStretchBltMode(Canvas.Handle, HalfTone);
{下面这句是把就是缩小或者放大,前5个参数是要显示的图象,后5个是原始图象,最后一个是模式}
stretchBlt(Canvas.Handle,0,0,Width,Height,DC,0,0,screen.Width,screen.Height,SRCCOPY);
releasedc(0,dc);
end;
image1.Picture.Assign(bmp);
end;
 
这个的失真比较严重,还是用gdi+里边的函数吧.具体搜一下,就好了
 
失真严重?? 楼上的试试再说.....这个和PS里缩小的效果没多大差别
 
不知道是要图象的缩小还是显示的缩小啊如果只是显示的缩小就用 img1.width:=img1.width div N;
img1.height:=img1.height div N;
如果是图象的缩小可以用:
img1.Canvas.StretchDraw(Rect(0,0,idestwidth,idestheight),BitpicSource);
img1.Refresh;
 
采用 StretchDraw 和 StretchBlt 的方法都是不妥当的,都会存在失真的问题(反复缩放几次就知道了,或者放大100倍看看。。。)
正解是采用座标空间转换
另:GDI内就有,不一定要用 GDI+
 
不能采用 StretchDraw 和 StretchBlt 等方法,应该使用座标空间转换.
 
StretchDraw我不太清楚,不过StretchBlt是可以达到平滑缩小而不会出现严重的失真现象

lxggc说的反复缩放几次就知道,我不明白...难道一个1000*1000的非矢量图象被缩小到100*100以后,再放大到1000*1000后,能和原始的图象完全一样?
或者一个图象被放大100倍以后能够达到完全平滑而不出现锯齿?
难道坐标空间转换能够使一个非矢量图进行缩放操作后能够达到矢量图的缩放效果?

说StretchBlt会失真的估计是没调整参数,就是
SetStretchBltMode(Canvas.Handle, HalfTone);
这句,第2个参数是缩放模式,有
BLACKONWHITE = 1;
WHITEONBLACK = 2;
COLORONCOLOR = 3;
HALFTONE = 4;
MAXSTRETCHBLTMODE = 4;
这几种模式
 
是图像本身的放大缩小还是Image:TImage?如果是图像本身,那么就会有失真,可以用Image :TImage来承载着幅图像。以达到视觉的放大缩小,但是图像本身不会发生变化。
我写了一个类:
unit imageinfo;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, ComCtrls, ToolWin, StdCtrls, ExtCtrls, Buttons,RTLConsts,
CSBitBtn, CSComboBox, CSEdit,JPEG;
type
TImageShow = class
private
FStream: TMemoryStream;
FImage: TImage;
FMsgStr : string;
FZoomStep : integer;
FImageStrBox: TScrollBox;
FSize: Integer;
FWidth : integer;
FHeight : Integer;
NWidth : Integer;
NHeight : Integer;
procedure ImageInit;
procedure changeMsg;
public
constructor Create(Image: TImage; OwnerPanel: TScrollBox);
destructor Destroy; override;
public
property Size: Integer read FSize write FSize;
property MsgStr: string read FMsgStr write FMsgStr;
property Stream: TMemoryStream read FStream write FStream;
public
function GetImageSize: LongInt;
procedure ShowImage(Stream: TMemoryStream);
procedure ZoomOut;
procedure ZoomIn;
procedure TrueSize;
function GetImageMsgStr: string;
end;
implementation

{TImageShow}
constructor TImageShow.Create(Image: TImage; OwnerPanel: TScrollBox);
begin
FZoomStep := 0;
FImage := Image;
FStream := TMemoryStream.Create;
if Assigned(FImage) then
begin
ImageInit;
end;
FImageStrBox := OwnerPanel;
end;
destructor TImageShow.Destroy;
begin
if FStream <> nil then
begin
FStream.Free;
FStream := nil;
end;
inherited;
end;
procedure TImageShow.ShowImage(Stream: TMemoryStream);
var
ajpeg:TJpegImage;
begin
if Stream.Size<=0 then exit;
ajpeg:=TJpegImage.Create;
stream.Position := 0;
ajpeg.LoadFromStream(Stream);
FStream := Stream;
Fsize :=FStream.Size;
FWidth := ajpeg.Width;
FHeight := ajpeg.Height;
FImage.Width:= FWidth;
FImage.Height:= FHeight;
NWidth := FWidth;
NHeight := FHeight;
FMsgStr := Format('尺寸:%dx%d 像素, 大小:%d字节, 状态:[%s]',[FWidth,FHeight,FSize,'原始大小']);
FImage.Picture.Assign(ajpeg);
FreeAndNil(ajpeg);
end;
function TImageShow.GetImageMsgStr: string;
begin
result :=MsgStr;
end;
procedure TImageShow.ImageInit;
begin
FImage.Align := alNone;
FImage.Stretch := True;
FImage.AutoSize := False;
FImage.Center := False;
FImage.Proportional := true;
end;
procedure TImageShow.changeMsg;
begin
if FZoomStep>0 then
FMsgStr := Format('尺寸:%dx%d 像素, 大小:%d字节, 状态:[放大百分之%d]',[NWidth,NHeight,FSize,FZoomStep*10]);
if FZoomStep=0 then
FMsgStr := Format('尺寸:%dx%d 像素, 大小:%d字节, 状态:[%s]',[NWidth,NHeight,FSize,'原始大小']);
if FZoomStep<0 then
FMsgStr := Format('尺寸:%dx%d 像素, 大小:%d字节, 状态:[缩小百分之%d]',[NWidth,NHeight,FSize,-FZoomStep*10]);
end;
procedure TImageShow.ZoomOut;
begin
if Fimage.Picture<>nil then
begin
FZoomStep := FZoomStep + 1;
NWidth := trunc(FWidth * (1.0+FZoomStep*0.1));
NHeight := trunc(FHeight * (1.0+FZoomStep*0.1));
changeMsg;
FImage.Width := NWidth;
FImage.Height := NHeight;
end;
end;
procedure TImageShow.ZoomIn;
begin
if Fimage.Picture<>nil then
begin
FZoomStep := FZoomStep - 1;
if FZoomStep<-9 then FZoomStep:=-9;
NWidth := trunc(FWidth * (1.0+FZoomStep*0.1));
NHeight := trunc(FHeight * (1.0+FZoomStep*0.1));
changeMsg;
FImage.Width := NWidth;
FImage.Height := NHeight;
end;
end;
procedure TImageShow.TrueSize;
begin
if Fimage.Picture<>nil then
begin
FZoomStep := 0;
NWidth := FWidth;
NHeight := FHeight;
changeMsg;
FImage.Width := NWidth;
FImage.Height := NHeight;
FImage.Left:=1;
FImage.Top:=1;
end;
end;
function TImageShow.GetImageSize: LongInt;
begin
result := Fsize;
end;
end.
 
这里的CSBitBtn, CSComboBox, CSEdit,单元式私有的 。没有必要要,去掉就可以了。
 
谢谢大家
 
学习了,呵呵
 
to hs-kill:
楼主说的特指矢量图,而矢量图的特点就是支持无限制的缩放而不失真,比如CAD软件,如果是Bmp图像,那肯定是不行的,比如数码照片你放大1000倍,看到的估计也就是马赛克了。在Word等软件中,放大都是采用矢量放大而不是 Stretch...
 

Similar threads

后退
顶部