请问,象photoshop里扭曲滤镜里的挤压效果是用什么算法实现的?(100分)

  • 主题发起人 主题发起人 carol79
  • 开始时间 开始时间
C

carol79

Unregistered / Unconfirmed
GUEST, unregistred user!
请问,象photoshop里扭曲滤镜里的挤压效果是用什么算法实现的?或者哪儿有相关的资料?
 
试试这个

代码:
procedure TMainForm.Twist(var Bmp, Dst: TBitmap; Amount: integer);
var
fxmid, fymid : Single;
txmid, tymid : Single;
fx,fy : Single;
tx2, ty2 : Single;
r : Single;
theta : Single;
ifx, ify : integer;
dx, dy : Single;
OFFSET : Single;
ty, tx : Integer;
weight_x, weight_y : array[0..1] of Single;
weight : Single;
new_red, new_green : Integer;
new_blue : Integer;
total_red, total_green : Single;
total_blue : Single;
ix, iy : Integer;
sli, slo : PBytearray;

function ArcTan2(xt,yt : Single): Single;
begin
if xt = 0 then
if yt > 0 then
Result := Pi/2
else
Result := -(Pi/2)
else begin
Result := ArcTan(yt/xt);
if xt < 0 then
Result := Pi + ArcTan(yt/xt);
end;
end;

begin
OFFSET := -(Pi/2);
dx := Bmp.Width - 1;
dy := Bmp.Height - 1;
r := Sqrt(dx * dx + dy * dy);
tx2 := r;
ty2 := r;
txmid := (Bmp.Width-1)/2; //Adjust these to move center of rotation
tymid := (Bmp.Height-1)/2; //Adjust these to move ......
fxmid := (Bmp.Width-1)/2;
fymid := (Bmp.Height-1)/2;
if tx2 >= Bmp.Width then tx2 := Bmp.Width-1;
if ty2 >= Bmp.Height then ty2 := Bmp.Height-1;

for ty := 0 to Round(ty2) do begin
for tx := 0 to Round(tx2) do begin
dx := tx - txmid;
dy := ty - tymid;
r := Sqrt(dx * dx + dy * dy);
if r = 0 then begin
fx := 0;
fy := 0;
end
else begin
theta := ArcTan2(dx,dy) - r/Amount - OFFSET;
fx := r * Cos(theta);
fy := r * Sin(theta);
end;
fx := fx + fxmid;
fy := fy + fymid;

ify := Trunc(fy);
ifx := Trunc(fx);
// Calculate the weights.
if fy >= 0 then begin
weight_y[1] := fy - ify;
weight_y[0] := 1 - weight_y[1];
end else begin
weight_y[0] := -(fy - ify);
weight_y[1] := 1 - weight_y[0];
end;
if fx >= 0 then begin
weight_x[1] := fx - ifx;
weight_x[0] := 1 - weight_x[1];
end else begin
weight_x[0] := -(fx - ifx);
Weight_x[1] := 1 - weight_x[0];
end;

if ifx < 0 then
ifx := Bmp.Width-1-(-ifx mod Bmp.Width)
else if ifx > Bmp.Width-1 then
ifx := ifx mod Bmp.Width;
if ify < 0 then
ify := Bmp.Height-1-(-ify mod Bmp.Height)
else if ify > Bmp.Height-1 then
ify := ify mod Bmp.Height;

total_red := 0.0;
total_green := 0.0;
total_blue := 0.0;
for ix := 0 to 1 do begin
for iy := 0 to 1 do begin
if ify + iy < Bmp.Height then
sli := Bmp.scanline[ify + iy]
else
sli := Bmp.scanline[Bmp.Height - ify - iy];
if ifx + ix < Bmp.Width then begin
new_red := sli[(ifx + ix)*3];
new_green := sli[(ifx + ix)*3+1];
new_blue := sli[(ifx + ix)*3+2];
end
else begin
new_red := sli[(Bmp.Width - ifx - ix)*3];
new_green := sli[(Bmp.Width - ifx - ix)*3+1];
new_blue := sli[(Bmp.Width - ifx - ix)*3+2];
end;
weight := weight_x[ix] * weight_y[iy];
total_red := total_red + new_red * weight;
total_green := total_green + new_green * weight;
total_blue := total_blue + new_blue * weight;
end;
end;
slo := Dst.scanline[ty];
slo[tx*3] := Round(total_red);
slo[tx*3+1] := Round(total_green);
slo[tx*3+2] := Round(total_blue);
end;
end;
 
结果出不来,不知道是什么原因,发贴人可以给我答案吗?
 
procedure TMainForm.ImageTwistClick(Sender: TObject);
var
bm2:tbitmap;
clip:TBitmap;
am:integer;
begin
clip:= TBitmap.Create;
clip.Assign(childForm.Image1.picture.bitmap);
bm2:=tbitmap.create;
bm2.width:=clip.width;
bm2.height:=clip.height;
bm2.pixelformat:=pf24bit;
am:=150;//strtoint(Edit1.text);
twist(clip,bm2,am);
childForm.Image1.picture.bitmap.assign(bm2);
Bm2.Free;
clip.free;
end;
 
amount的值只能取150?还是哪个范围内的值均可?
 
amount的值是在一个范围,你可以取不同的值看看,扭曲程度是不同的
说明一下,上面的扭曲算法来自 左轻侯 大侠,效果还行,就是速度慢了点
 
后退
顶部