extinterpolation.pp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519
  1. unit extinterpolation;
  2. {
  3. Some more interpolation filters for TFPCanvas.StretchDraw:
  4. Bessel, Gaussian and Sinc are infinite impulse response (IIR),
  5. the other are finite impulse response (FIR). The implementation
  6. of Bessel and Sinc are windowed with Blackman filter.
  7. }
  8. {$mode objfpc}{$H+}
  9. interface
  10. uses
  11. Math, Classes, SysUtils, FPImage, FPCanvas;
  12. type
  13. { TBlackmanInterpolation }
  14. TBlackmanInterpolation = class (TFPBaseInterpolation)
  15. protected
  16. function Filter (x : double) : double; override;
  17. function MaxSupport : double; override;
  18. end;
  19. { TBlackmanSincInterpolation }
  20. TBlackmanSincInterpolation = class (TFPBaseInterpolation)
  21. protected
  22. function Filter (x : double) : double; override;
  23. function MaxSupport : double; override;
  24. end;
  25. { TBlackmanBesselInterpolation }
  26. TBlackmanBesselInterpolation = class (TFPBaseInterpolation)
  27. protected
  28. function Filter (x : double) : double; override;
  29. function MaxSupport : double; override;
  30. end;
  31. { TGaussianInterpolation }
  32. TGaussianInterpolation = class (TFPBaseInterpolation)
  33. protected
  34. function Filter (x : double) : double; override;
  35. function MaxSupport : double; override;
  36. end;
  37. { TBoxInterpolation }
  38. TBoxInterpolation = class (TFPBaseInterpolation)
  39. protected
  40. function Filter (x : double) : double; override;
  41. function MaxSupport : double; override;
  42. end;
  43. { THermiteInterpolation }
  44. THermiteInterpolation = class (TFPBaseInterpolation)
  45. protected
  46. function Filter (x : double) : double; override;
  47. function MaxSupport : double; override;
  48. end;
  49. { TLanczosInterpolation }
  50. TLanczosInterpolation = class (TFPBaseInterpolation)
  51. protected
  52. function Filter (x : double) : double; override;
  53. function MaxSupport : double; override;
  54. end;
  55. { TQuadraticInterpolation }
  56. TQuadraticInterpolation = class (TFPBaseInterpolation)
  57. protected
  58. function Filter (x : double) : double; override;
  59. function MaxSupport : double; override;
  60. end;
  61. { TCubicInterpolation }
  62. TCubicInterpolation = class (TFPBaseInterpolation)
  63. protected
  64. function Filter (x : double) : double; override;
  65. function MaxSupport : double; override;
  66. end;
  67. { TCatromInterpolation }
  68. TCatromInterpolation = class (TFPBaseInterpolation)
  69. protected
  70. function Filter (x : double) : double; override;
  71. function MaxSupport : double; override;
  72. end;
  73. { TBilineairInterpolation }
  74. TBilineairInterpolation = class (TFPBaseInterpolation)
  75. protected
  76. function Filter (x : double) : double; override;
  77. function MaxSupport : double; override;
  78. end;
  79. { THanningInterpolation }
  80. THanningInterpolation = class (TFPBaseInterpolation)
  81. protected
  82. function Filter (x : double) : double; override;
  83. function MaxSupport : double; override;
  84. end;
  85. { THammingInterpolation }
  86. THammingInterpolation = class (TFPBaseInterpolation)
  87. protected
  88. function Filter (x : double) : double; override;
  89. function MaxSupport : double; override;
  90. end;
  91. implementation
  92. // BesselOrderOne: computes Bessel function of x in the first kind of order 0
  93. function J1 (x : double) : double;
  94. const Pone : array[0..8] of double =
  95. ( 0.581199354001606143928050809e+21,
  96. -0.6672106568924916298020941484e+20,
  97. 0.2316433580634002297931815435e+19,
  98. -0.3588817569910106050743641413e+17,
  99. 0.2908795263834775409737601689e+15,
  100. -0.1322983480332126453125473247e+13,
  101. 0.3413234182301700539091292655e+10,
  102. -0.4695753530642995859767162166e+7,
  103. 0.270112271089232341485679099e+4
  104. );
  105. Qone : array [0..8] of double =
  106. ( 0.11623987080032122878585294e+22,
  107. 0.1185770712190320999837113348e+20,
  108. 0.6092061398917521746105196863e+17,
  109. 0.2081661221307607351240184229e+15,
  110. 0.5243710262167649715406728642e+12,
  111. 0.1013863514358673989967045588e+10,
  112. 0.1501793594998585505921097578e+7,
  113. 0.1606931573481487801970916749e+4,
  114. 0.1e+1
  115. );
  116. var p,q : double;
  117. r : 0..8;
  118. begin
  119. p := Pone[8];
  120. q := Qone[8];
  121. for r := 7 downto 0 do
  122. begin
  123. p := p*x*x+pOne[r];
  124. q := q*X*X+Qone[r];
  125. end;
  126. result := p / q;
  127. end;
  128. function P1 (x : double) : double;
  129. const Pone : array[0..5] of double =
  130. ( 0.352246649133679798341724373e+5,
  131. 0.62758845247161281269005675e+5,
  132. 0.313539631109159574238669888e+5,
  133. 0.49854832060594338434500455e+4,
  134. 0.2111529182853962382105718e+3,
  135. 0.12571716929145341558495e+1
  136. );
  137. Qone : array [0..5] of double =
  138. ( 0.352246649133679798068390431e+5,
  139. 0.626943469593560511888833731e+5,
  140. 0.312404063819041039923015703e+5,
  141. 0.4930396490181088979386097e+4,
  142. 0.2030775189134759322293574e+3,
  143. 0.1e+1
  144. );
  145. var x8,p,q : double;
  146. r : 0..5;
  147. begin
  148. p := Pone[5];
  149. q := Qone[5];
  150. x8 := 8.0 / x;
  151. for r := 4 downto 0 do
  152. begin
  153. p := p*x8*x8+pOne[r];
  154. q := q*x8*x8+Qone[r];
  155. end;
  156. result := p / q;
  157. end;
  158. function Q1 (x : double) : double;
  159. const Pone : array[0..5] of double =
  160. ( 0.3511751914303552822533318e+3,
  161. 0.7210391804904475039280863e+3,
  162. 0.4259873011654442389886993e+3,
  163. 0.831898957673850827325226e+2,
  164. 0.45681716295512267064405e+1,
  165. 0.3532840052740123642735e-1
  166. );
  167. Qone : array [0..5] of double =
  168. ( 0.74917374171809127714519505e+4,
  169. 0.154141773392650970499848051e+5,
  170. 0.91522317015169922705904727e+4,
  171. 0.18111867005523513506724158e+4,
  172. 0.1038187585462133728776636e+3,
  173. 0.1e+1
  174. );
  175. var x8,p,q : double;
  176. r : 0..5;
  177. begin
  178. p := Pone[5];
  179. q := Qone[5];
  180. x8 := 8.0 / x;
  181. for r := 4 downto 0 do
  182. begin
  183. p := p*x8*x8+pOne[r];
  184. q := q*x8*x8+Qone[r];
  185. end;
  186. result := p / q;
  187. end;
  188. function BesselOrderOne (x : double) : double;
  189. var p,OneOverSqrt2,sinx,cosx : double;
  190. begin
  191. if x = 0.0 then
  192. result := 0.0
  193. else
  194. begin
  195. p := x;
  196. if x < 0.0 then
  197. x := -x;
  198. if x < 8.0 then
  199. result := p * J1(x)
  200. else
  201. begin
  202. OneOverSqrt2 := 1.0 / sqrt(2.0);
  203. sinx := sin(x);
  204. cosx := cos(x);
  205. result := sqrt(2.0/(PI*x)) *
  206. ( P1(x)*(OneOverSqrt2*(sinx-cosx))
  207. - 8.0/x*Q1(x)*(-OneOverSqrt2*(sinx+cosx))
  208. );
  209. if p < 0.0 then
  210. result := -result;
  211. end
  212. end;
  213. end;
  214. // Functions to aid calculations
  215. function Bessel (x : double) : double;
  216. begin
  217. if x = 0.0 then
  218. result := PI / 4.0
  219. else
  220. result := BesselOrderOne(PI * x) / (2.0 * x);
  221. end;
  222. function Sinc (x : double) : double;
  223. var xx : double;
  224. begin
  225. if x = 0.0 then
  226. result := 1.0
  227. else
  228. begin
  229. xx := PI*x;
  230. result := sin(xx) / (xx);
  231. end;
  232. end;
  233. function Blackman (x : double) : double;
  234. var xpi : double;
  235. begin
  236. xpi := PI * x;
  237. result := 0.42 + 0.5 * cos(xpi) + 0.08 * cos(2*xpi);
  238. end;
  239. { THermiteInterpolation }
  240. function THermiteInterpolation.Filter(x: double): double;
  241. begin
  242. if x < -1.0 then
  243. result := 0.0
  244. else if x < 0.0 then
  245. result := (2.0*(-x)-3.0)*(-x)*(-x)+1.0
  246. else if x < 1.0 then
  247. result := (2.0*x-3.0)*x*x+1.0
  248. else
  249. result := 0;
  250. end;
  251. function THermiteInterpolation.MaxSupport: double;
  252. begin
  253. result := 1.0;
  254. end;
  255. { TLanczosInterpolation }
  256. function TLanczosInterpolation.Filter(x: double): double;
  257. begin
  258. if x < -3.0 then
  259. result := 0.0
  260. else if x < 0.0 then
  261. result := sinc(-x)*sinc(-x/3.0)
  262. else if x < 3.0 then
  263. result := sinc(x)*sinc(x/3.0)
  264. else
  265. result := 0.0;
  266. end;
  267. function TLanczosInterpolation.MaxSupport: double;
  268. begin
  269. result := 3.0;
  270. end;
  271. { TQuadraticInterpolation }
  272. function TQuadraticInterpolation.Filter(x: double): double;
  273. begin
  274. if x < -1.5 then
  275. result := 0.0
  276. else if x < -0.5 then
  277. begin
  278. x := x + 1.5;
  279. result := 0.5*x*x;
  280. end
  281. else if x < 0.5 then
  282. result := 0.75 - x*x
  283. else if x < 1.5 then
  284. begin
  285. x := x - 1.5;
  286. result := 0.5*x*x;
  287. end
  288. else
  289. result := 0.0;
  290. end;
  291. function TQuadraticInterpolation.MaxSupport: double;
  292. begin
  293. result := 1.5;
  294. end;
  295. { TCubicInterpolation }
  296. function TCubicInterpolation.Filter(x: double): double;
  297. begin
  298. if x < -2.0 then
  299. result := 0.0
  300. else if x < -1.0 then
  301. begin
  302. x := x +2.0;
  303. result := x*x*x / 6.0;
  304. end
  305. else if x < 0.0 then
  306. result := (4.0+x*x*(-6.0-3.0*x)) / 6.0
  307. else if x < 1.0 then
  308. result := (4.0+x*x*(-6.0+3.0*x)) / 6.0
  309. else if x < 2.0 then
  310. begin
  311. x := 2.0 - x;
  312. result := x*x*x / 6.0;
  313. end
  314. else
  315. result := 0.0;
  316. end;
  317. function TCubicInterpolation.MaxSupport: double;
  318. begin
  319. result := 2.0;
  320. end;
  321. { TCatromInterpolation }
  322. function TCatromInterpolation.Filter(x: double): double;
  323. begin
  324. if x < -2.0 then
  325. result := 0.0
  326. else if x < -1.0 then
  327. result := 0.5*(4.0+x*(8.0+x*(5.0+x)))
  328. else if x < 0.0 then
  329. result := 0.5*(2.0+x*x*(-5.0-3.0*x))
  330. else if x < 1.0 then
  331. result := 0.5*(2.0+x*x*(-5.0+3.0*x))
  332. else if x < 2.0 then
  333. result := 0.5*(4.0+x*(-8.0+x*(5.0-x)))
  334. else
  335. result := 0.0;
  336. end;
  337. function TCatromInterpolation.MaxSupport: double;
  338. begin
  339. result := 2.0;
  340. end;
  341. { THanningInterpolation }
  342. function THanningInterpolation.Filter(x: double): double;
  343. begin
  344. if x < -1.0 then
  345. result := 0.0
  346. else if x <= 1.0 then
  347. result := 0.5+0.5*cos(PI*x)
  348. else
  349. result := 0.0;
  350. end;
  351. function THanningInterpolation.MaxSupport: double;
  352. begin
  353. result := 1.0;
  354. end;
  355. { THammingInterpolation }
  356. function THammingInterpolation.Filter(x: double): double;
  357. begin
  358. if x < -1.0 then
  359. result := 0.0
  360. else if x <= 1.0 then
  361. result := 0.54+0.46*cos(PI*x)
  362. else
  363. result := 0.0;
  364. end;
  365. function THammingInterpolation.MaxSupport: double;
  366. begin
  367. result := 1.0;
  368. end;
  369. { TBilineairInterpolation }
  370. function TBilineairInterpolation.Filter(x: double): double;
  371. begin
  372. if x < -1.0 then
  373. result := 0.0
  374. else if x < 0.0 then
  375. result := 1 + x
  376. else if x < 1.0 then
  377. result := 1 - x
  378. else
  379. result := 0.0;
  380. end;
  381. function TBilineairInterpolation.MaxSupport: double;
  382. begin
  383. result := 1.0;
  384. end;
  385. { TBoxInterpolation }
  386. function TBoxInterpolation.Filter(x: double): double;
  387. begin
  388. if x < -0.5 then
  389. result := 0.0
  390. else if x < 0.5 then
  391. result := 1.0
  392. else
  393. result := 0.0;
  394. end;
  395. function TBoxInterpolation.MaxSupport: double;
  396. begin
  397. result := 0.5;
  398. end;
  399. { TGaussianInterpolation }
  400. function TGaussianInterpolation.Filter(x: double): double;
  401. begin
  402. result := exp(-2.0*x*x) * sqrt(2.0/PI);
  403. end;
  404. function TGaussianInterpolation.MaxSupport: double;
  405. begin
  406. result := 1.25;
  407. end;
  408. { TBlackmanBesselInterpolation }
  409. function TBlackmanBesselInterpolation.Filter(x: double): double;
  410. begin
  411. result := Blackman(x/MaxSupport) * Bessel (x);
  412. end;
  413. function TBlackmanBesselInterpolation.MaxSupport: double;
  414. begin
  415. Result := 3.2383;
  416. end;
  417. { TBlackmanSincInterpolation }
  418. function TBlackmanSincInterpolation.Filter(x: double): double;
  419. begin
  420. Result := Blackman(x/MaxSupport) * Sinc(x);
  421. end;
  422. function TBlackmanSincInterpolation.MaxSupport: double;
  423. begin
  424. Result := 4.0;
  425. end;
  426. { TBlackmanInterpolation }
  427. function TBlackmanInterpolation.Filter(x: double): double;
  428. begin
  429. Result := Blackman (x);
  430. end;
  431. function TBlackmanInterpolation.MaxSupport: double;
  432. begin
  433. Result := 1.0;
  434. end;
  435. end.