应该是鱼眼算法吧,我就借花献佛吧
procedure FishEye(var Bmp, Dst: TBitmap; Amount: Extended);
var
xmid,ymid : Single;
fx,fy : Single;
r1, r2 : Single;
ifx, ify : integer;
dx, dy : Single;
rmax : 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;
begin
xmid := Bmp.Width/2;
ymid := Bmp.Height/2;
rmax := Dst.Width * Amount;
for ty := 0 to Dst.Height - 1 do begin
for tx := 0 to Dst.Width - 1 do begin
dx := tx - xmid;
dy := ty - ymid;
r1 := Sqrt(dx * dx + dy * dy);
if r1 = 0 then begin
fx := xmid;
fy := ymid;
end
else begin
r2 := rmax / 2 * (1 / (1 - r1/rmax) - 1);
fx := dx * r2 / r1 + xmid;
fy := dy * r2 / r1 + ymid;
end;
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;
end;