可以缩放图象显示大小,同时刷新屏幕显示,就可以了。
具体实现方法,可以用DirectDraw,OpenGL等等,也可以不用,都是可以的。
没有搞过图形的话,例子一下子不好说,到:gfody.com 去看看吧。
给一个用FASTLIB实现的例子:
program rotozoom;
{$R sunghi.res}
{$R *.res}
{$R-}
uses
Windows, Messages, FastDIB, FastFiles, FastBlend;
var
Dst,Src,Blur: TFastDIB;
Handle,hDC,Frames,Fps,i: Integer;
Filter: Boolean=True;
Motion: Boolean=False;
GotMsg: Boolean;
Msg: TMSG;
Pic: Integer=0;
mx,my: array[Word]of Integer; //mod table
const
ResNames: array[0..1]of string = ('sunghi1', 'sunghi2');
procedure UpdateFrame;
var
x,y,t1,t2,dx,dy,xd,yd,cx,cy,
sdx,sdy,isin,icos,ax,ay,ex,ey: Integer;
c00,c01,c10,c11: Byte;
pc,sp: PByte;
s: string;
begin
Inc(i);
xd:=((Src.Width shl 16)-(Dst.Width shl 16))div 2;
yd:=((Src.Height shl 16)-(Dst.Height shl 16))div 2;
cx:=Dst.Width shr 1;
cy:=Dst.Height shr 1;
isin:=Round(Sin(Cos(i/90)*15)*65536);
icos:=Round(Cos(Sin(i/360)*35)*65536);
ax:=(cx shl 16)-(icos*cx);
ay:=(cy shl 16)-(isin*cx);
pc:=Pointer(Dst.Bits);
for y:=0 to Dst.Height-1 do
begin
dy:=cy-y;
sdx:=(ax+(isin*dy))+xd;
sdy:=(ay-(icos*dy))+yd;
for x:=0 to Dst.Width-1 do
begin
dx:=Smallint(sdx shr 16);
dy:=Smallint(sdy shr 16);
// using a lookup table instead of mod
if dx<0 then dx:=Src.Width-mx[-dx]-2 else if dx>Src.Width-2 then dx:=mx[dx];
if dy<0 then dy:=Src.AbsHeight-my[-dy]-2 else if dy>Src.AbsHeight-2 then dy:=my[dy];
if Filter then
begin
sp:=@Src.Pixels8[dy,dx];
c00:=sp^; Inc(sp);
c01:=sp^; Inc(sp,Src.BWidth-1);
c10:=sp^; Inc(sp);
c11:=sp^;
ex:=sdx and $FFFF;
ey:=sdy and $FFFF;
t1:=((((c01-c00)*ex)shr 16)+c00)and $FF;
t2:=((((c11-c10)*ex)shr 16)+c10)and $FF;
pc^:=(((t2-t1)*ey)shr 16)+t1;
end else pc^:=Src.Pixels8[dy,dx];
Inc(sdx,icos);
Inc(sdy,isin);
Inc(pc);
end;
Inc(pc,Dst.Gap);
end;
Str(Fps,s);
if i<500 then
begin
Dst.TextOut(5,0,'sung hi rotozoomer - g0rdy');
Dst.TextOut(5,15,'right-click: toggle feedback');
Dst.TextOut(5,30,'left-click: toggle bilinear filter');
Dst.TextOut(5,45,'press a key: change picture');
Dst.TextOut(5,60,s);
end else Dst.TextOut(5,0,s);
if Motion then
begin
Blur.SetSize(Dst.Width,Dst.Height,8);
AvgBlend(Blur,Blur,Dst);
Blur.Draw(hDC,0,0);
end else Dst.Draw(hDC,0,0);
Inc(Frames);
end;
procedure FillModTable;
var
x,y,i: Integer;
begin
x:=0; y:=0;
for i:=0 to 65535 do
begin
mx
:=x;
my:=y;
Inc(x); if x=Src.Width-1 then x:=0;
Inc; if y=Src.Height-1 then y:=0;
end;
end;
function WindowProc(hWnd,uMsg,wParam,lParam:Longint):Longint; stdcall;
var
ps: TPaintStruct;
begin
case uMsg of
WM_KEYDOWN:
begin
if Pic=0 then Inc(Pic) else Pic:=0;
LoadJPGRes(Src,hInstance,ResNames[Pic],'binary',True);
FillModTable;
Result:=0;
end;
WM_LBUTTONDOWN:
begin
Filter:=not Filter;
Result:=0;
end;
WM_RBUTTONDOWN:
begin
FillChar(Blur.Bits^,Blur.Size,0);
Motion:=not Motion;
Result:=0;
end;
WM_DESTROY:
begin
Src.Free;
Dst.Free;
if Blur<>nil then Blur.Free;
KillTimer(Handle,0);
ReleaseDC(Handle,hDC);
ExitProcess(hInstance);
Result:=0;
end;
WM_PAINT:
begin
BeginPaint(hWnd,ps);
Dst.Draw(ps.hDC,0,0);
EndPaint(hWnd,ps);
Result:=0;
end;
WM_SIZE:
begin
Dst.SetSize(lParam and $FFFF,lParam shr 16,8);
Dst.SetTransparent(True);
Dst.SetFontEx('Tahoma',5,12,800,False,False,False);
Result:=0;
end;
WM_TIMER:
begin
Fps:=Frames;
Frames:=0;
Result:=0;
end;
else Result:=DefWindowProc(hWnd,uMsg,wParam,lParam);
end;
end;
begin
Src:=TFastDIB.Create;
if HasJPG then LoadJPGRes(Src,hInstance,'sunghi1','binary',True) else
begin
Src.SetSize(300,50,8);
Src.FillColors(0,255,[tfBlack,FRGB(0,100,128),tfWhite]);
Src.SetBkColor(0);
Src.SetTextColor(RGB(255,255,255));
Src.TextOut(0,0,'Intel?Jpeg Library (ijl15.dll) not found!');
end;
FillModTable;
Blur:=TFastDIB.Create;
Blur.FillColors(0,255,[tfBlack,FRGB(0,100,128),tfWhite]);
Dst:=TFastDIB.Create;
Dst.SetSize(500,400,8);
Dst.FillColors(0,255,[tfBlack,FRGB(0,100,128),tfWhite]);
Dst.SetFontEx('Tahoma',5,12,800,False,False,False);
Dst.SetTransparent(True);
hDC:=GetDC(Handle);
Handle:=CreateWindow('#32770','rotozoom - gordy',
WS_VISIBLE or WS_SYSMENU or WS_SIZEBOX,0,0,
(GetSystemMetrics(SM_CXFIXEDFRAME)shl 1)+Dst.Width,
(GetSystemMetrics(SM_CYFIXEDFRAME)shl 1)+GetSystemMetrics(SM_CYCAPTION)+Dst.AbsHeight,
0,0,hInstance,nil);
SetWindowLong(Handle,GWL_WNDPROC,Longint(@WindowProc));
hDC:=GetDC(Handle);
SetTimer(Handle,0,1000,nil);
while Msg.Message<>WM_QUIT do
begin
GotMsg:=PeekMessage(Msg,0,0,0,PM_REMOVE);
if GotMsg then DispatchMessage(Msg) else UpdateFrame;
end;
end.