123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- 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.
|