Repository URL to install this package:
Version:
3.0.0 ▾
|
unit extinterpolation;
{
Some more interpolation filters for TFPCanvas.StretchDraw:
Bessel, Gaussian and Sinc are infinite impulse response (IIR),
the other are finite impulse response (FIR). The implementation
of Bessel and Sinc are windowed with Blackman filter.
}
{$mode objfpc}{$H+}
interface
uses
Math, Classes, SysUtils, FPImage, FPCanvas;
type
{ TBlackmanInterpolation }
TBlackmanInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TBlackmanSincInterpolation }
TBlackmanSincInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TBlackmanBesselInterpolation }
TBlackmanBesselInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TGaussianInterpolation }
TGaussianInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TBoxInterpolation }
TBoxInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ THermiteInterpolation }
THermiteInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TLanczosInterpolation }
TLanczosInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TQuadraticInterpolation }
TQuadraticInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TCubicInterpolation }
TCubicInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TCatromInterpolation }
TCatromInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ TBilineairInterpolation }
TBilineairInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ THanningInterpolation }
THanningInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
{ THammingInterpolation }
THammingInterpolation = class (TFPBaseInterpolation)
protected
function Filter (x : double) : double; override;
function MaxSupport : double; override;
end;
implementation
// BesselOrderOne: computes Bessel function of x in the first kind of order 0
function J1 (x : double) : double;
const Pone : array[0..8] of double =
( 0.581199354001606143928050809e+21,
-0.6672106568924916298020941484e+20,
0.2316433580634002297931815435e+19,
-0.3588817569910106050743641413e+17,
0.2908795263834775409737601689e+15,
-0.1322983480332126453125473247e+13,
0.3413234182301700539091292655e+10,
-0.4695753530642995859767162166e+7,
0.270112271089232341485679099e+4
);
Qone : array [0..8] of double =
( 0.11623987080032122878585294e+22,
0.1185770712190320999837113348e+20,
0.6092061398917521746105196863e+17,
0.2081661221307607351240184229e+15,
0.5243710262167649715406728642e+12,
0.1013863514358673989967045588e+10,
0.1501793594998585505921097578e+7,
0.1606931573481487801970916749e+4,
0.1e+1
);
var p,q : double;
r : 0..8;
begin
p := Pone[8];
q := Qone[8];
for r := 7 downto 0 do
begin
p := p*x*x+pOne[r];
q := q*X*X+Qone[r];
end;
result := p / q;
end;
function P1 (x : double) : double;
const Pone : array[0..5] of double =
( 0.352246649133679798341724373e+5,
0.62758845247161281269005675e+5,
0.313539631109159574238669888e+5,
0.49854832060594338434500455e+4,
0.2111529182853962382105718e+3,
0.12571716929145341558495e+1
);
Qone : array [0..5] of double =
( 0.352246649133679798068390431e+5,
0.626943469593560511888833731e+5,
0.312404063819041039923015703e+5,
0.4930396490181088979386097e+4,
0.2030775189134759322293574e+3,
0.1e+1
);
var x8,p,q : double;
r : 0..5;
begin
p := Pone[5];
q := Qone[5];
x8 := 8.0 / x;
for r := 4 downto 0 do
begin
p := p*x8*x8+pOne[r];
q := q*x8*x8+Qone[r];
end;
result := p / q;
end;
function Q1 (x : double) : double;
const Pone : array[0..5] of double =
( 0.3511751914303552822533318e+3,
0.7210391804904475039280863e+3,
0.4259873011654442389886993e+3,
0.831898957673850827325226e+2,
0.45681716295512267064405e+1,
0.3532840052740123642735e-1
);
Qone : array [0..5] of double =
( 0.74917374171809127714519505e+4,
0.154141773392650970499848051e+5,
0.91522317015169922705904727e+4,
0.18111867005523513506724158e+4,
0.1038187585462133728776636e+3,
0.1e+1
);
var x8,p,q : double;
r : 0..5;
begin
p := Pone[5];
q := Qone[5];
x8 := 8.0 / x;
for r := 4 downto 0 do
begin
p := p*x8*x8+pOne[r];
q := q*x8*x8+Qone[r];
end;
result := p / q;
end;
function BesselOrderOne (x : double) : double;
var p,OneOverSqrt2,sinx,cosx : double;
begin
if x = 0.0 then
result := 0.0
else
begin
p := x;
if x < 0.0 then
x := -x;
if x < 8.0 then
result := p * J1(x)
else
begin
OneOverSqrt2 := 1.0 / sqrt(2.0);
sinx := sin(x);
cosx := cos(x);
result := sqrt(2.0/(PI*x)) *
( P1(x)*(OneOverSqrt2*(sinx-cosx))
- 8.0/x*Q1(x)*(-OneOverSqrt2*(sinx+cosx))
);
if p < 0.0 then
result := -result;
end
end;
end;
// Functions to aid calculations
function Bessel (x : double) : double;
begin
if x = 0.0 then
result := PI / 4.0
else
result := BesselOrderOne(PI * x) / (2.0 * x);
end;
function Sinc (x : double) : double;
var xx : double;
begin
if x = 0.0 then
result := 1.0
else
begin
xx := PI*x;
result := sin(xx) / (xx);
end;
end;
function Blackman (x : double) : double;
var xpi : double;
begin
xpi := PI * x;
result := 0.42 + 0.5 * cos(xpi) + 0.08 * cos(2*xpi);
end;
{ THermiteInterpolation }
function THermiteInterpolation.Filter(x: double): double;
begin
if x < -1.0 then
result := 0.0
else if x < 0.0 then
result := (2.0*(-x)-3.0)*(-x)*(-x)+1.0
else if x < 1.0 then
result := (2.0*x-3.0)*x*x+1.0
else
result := 0;
end;
function THermiteInterpolation.MaxSupport: double;
begin
result := 1.0;
end;
{ TLanczosInterpolation }
function TLanczosInterpolation.Filter(x: double): double;
begin
if x < -3.0 then
result := 0.0
else if x < 0.0 then
result := sinc(-x)*sinc(-x/3.0)
else if x < 3.0 then
result := sinc(x)*sinc(x/3.0)
else
result := 0.0;
end;
function TLanczosInterpolation.MaxSupport: double;
begin
result := 3.0;
end;
{ TQuadraticInterpolation }
function TQuadraticInterpolation.Filter(x: double): double;
begin
if x < -1.5 then
result := 0.0
else if x < -0.5 then
begin
x := x + 1.5;
result := 0.5*x*x;
end
else if x < 0.5 then
result := 0.75 - x*x
else if x < 1.5 then
begin
x := x - 1.5;
result := 0.5*x*x;
end
else
result := 0.0;
end;
function TQuadraticInterpolation.MaxSupport: double;
begin
result := 1.5;
end;
{ TCubicInterpolation }
function TCubicInterpolation.Filter(x: double): double;
begin
if x < -2.0 then
result := 0.0
else if x < -1.0 then
begin
x := x +2.0;
result := x*x*x / 6.0;
end
else if x < 0.0 then
result := (4.0+x*x*(-6.0-3.0*x)) / 6.0
else if x < 1.0 then
result := (4.0+x*x*(-6.0+3.0*x)) / 6.0
else if x < 2.0 then
begin
x := 2.0 - x;
result := x*x*x / 6.0;
end
else
result := 0.0;
end;
function TCubicInterpolation.MaxSupport: double;
begin
result := 2.0;
end;
{ TCatromInterpolation }
function TCatromInterpolation.Filter(x: double): double;
begin
if x < -2.0 then
result := 0.0
else if x < -1.0 then
result := 0.5*(4.0+x*(8.0+x*(5.0+x)))
else if x < 0.0 then
result := 0.5*(2.0+x*x*(-5.0-3.0*x))
else if x < 1.0 then
result := 0.5*(2.0+x*x*(-5.0+3.0*x))
else if x < 2.0 then
result := 0.5*(4.0+x*(-8.0+x*(5.0-x)))
else
result := 0.0;
end;
function TCatromInterpolation.MaxSupport: double;
begin
result := 2.0;
end;
{ THanningInterpolation }
function THanningInterpolation.Filter(x: double): double;
begin
if x < -1.0 then
result := 0.0
else if x <= 1.0 then
result := 0.5+0.5*cos(PI*x)
else
result := 0.0;
end;
function THanningInterpolation.MaxSupport: double;
begin
result := 1.0;
end;
{ THammingInterpolation }
function THammingInterpolation.Filter(x: double): double;
begin
if x < -1.0 then
result := 0.0
else if x <= 1.0 then
result := 0.54+0.46*cos(PI*x)
else
result := 0.0;
end;
function THammingInterpolation.MaxSupport: double;
begin
result := 1.0;
end;
{ TBilineairInterpolation }
function TBilineairInterpolation.Filter(x: double): double;
begin
if x < -1.0 then
result := 0.0
else if x < 0.0 then
result := 1 + x
else if x < 1.0 then
result := 1 - x
else
result := 0.0;
end;
function TBilineairInterpolation.MaxSupport: double;
begin
result := 1.0;
end;
{ TBoxInterpolation }
function TBoxInterpolation.Filter(x: double): double;
begin
if x < -0.5 then
result := 0.0
else if x < 0.5 then
result := 1.0
else
result := 0.0;
end;
function TBoxInterpolation.MaxSupport: double;
begin
result := 0.5;
end;
{ TGaussianInterpolation }
function TGaussianInterpolation.Filter(x: double): double;
begin
result := exp(-2.0*x*x) * sqrt(2.0/PI);
end;
function TGaussianInterpolation.MaxSupport: double;
begin
result := 1.25;
end;
{ TBlackmanBesselInterpolation }
function TBlackmanBesselInterpolation.Filter(x: double): double;
begin
result := Blackman(x/MaxSupport) * Bessel (x);
end;
function TBlackmanBesselInterpolation.MaxSupport: double;
begin
Result := 3.2383;
end;
{ TBlackmanSincInterpolation }
function TBlackmanSincInterpolation.Filter(x: double): double;
begin
Result := Blackman(x/MaxSupport) * Sinc(x);
end;
function TBlackmanSincInterpolation.MaxSupport: double;
begin
Result := 4.0;
end;
{ TBlackmanInterpolation }
function TBlackmanInterpolation.Filter(x: double): double;
begin
Result := Blackman (x);
end;
function TBlackmanInterpolation.MaxSupport: double;
begin
Result := 1.0;
end;
end.