fpinterpolation.inc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. { TFPCustomInterpolation }
  2. procedure TFPCustomInterpolation.Initialize(aimage: TFPCustomImage; acanvas: TFPCustomCanvas);
  3. begin
  4. fimage := aimage;
  5. fcanvas := acanvas;
  6. end;
  7. { TFPBaseInterpolation }
  8. type
  9. TInterpolationContribution = record
  10. weight : double;
  11. place : integer;
  12. end;
  13. function ColorRound (c : double) : word;
  14. begin
  15. if c > $FFFF then
  16. result := $FFFF
  17. else if c < 0.0 then
  18. result := 0
  19. else
  20. result := round(c);
  21. end;
  22. procedure TFPBaseInterpolation.Horizontal (width : integer);
  23. var x,y,r : integer;
  24. start, stop, maxcontribs : integer;
  25. center, re,gr,bl, density : double;
  26. contributions : array[0..10] of TInterpolationContribution;
  27. dif, w, gamma, a : double;
  28. c : TFPColor;
  29. begin
  30. for x := 0 to width-1 do
  31. begin
  32. center := x * xfactor;
  33. start := round (center-xsupport);
  34. if start < 0 then
  35. start := 0;
  36. stop := round(center+xsupport);
  37. if stop >= image.Width then
  38. stop := image.Width-1;
  39. density := 0.0;
  40. maxcontribs := -1;
  41. for r := start to stop do
  42. begin
  43. dif := r - center;
  44. w := Filter (dif);
  45. if w > 0.0 then
  46. begin
  47. inc (maxcontribs);
  48. with contributions[maxcontribs] do
  49. begin
  50. weight := w;
  51. density := density + w;
  52. place := r;
  53. end;
  54. end;
  55. end;
  56. if (density <> 0.0) and (density <> 1.0) then
  57. begin
  58. density := 1.0 / density;
  59. for r := 0 to maxcontribs do
  60. contributions[r].weight := contributions[r].weight * density;
  61. end;
  62. for y := 0 to image.height-1 do
  63. begin
  64. gamma := 0.0;
  65. re := 0.0;
  66. gr := 0.0;
  67. bl := 0.0;
  68. for r := 0 to maxcontribs do
  69. with contributions[r] do
  70. with image.colors[place,y] do
  71. begin
  72. a := weight * alpha / $FFFF;
  73. re := re + a * image.colors[place,y].red;
  74. gr := gr + a * image.colors[place,y].green;
  75. bl := bl + a * image.colors[place,y].blue;
  76. gamma := gamma + a;
  77. end;
  78. with c do
  79. begin
  80. red := ColorRound (re);
  81. green := ColorRound (gr);
  82. blue := ColorRound (bl);
  83. alpha := ColorRound (gamma * $FFFF) ;
  84. end;
  85. tempimage.colors[x,y] := c;
  86. end;
  87. end;
  88. end;
  89. procedure TFPBaseInterpolation.vertical(dx,dy,width,height: integer);
  90. var x,y,r : integer;
  91. start, stop, maxcontribs : integer;
  92. center, re,gr,bl, density : double;
  93. contributions : array[0..10] of TInterpolationContribution;
  94. dif, w, gamma, a : double;
  95. c : TFPColor;
  96. begin
  97. for y := 0 to height-1 do
  98. begin
  99. center := y * yfactor;
  100. start := round (center-ysupport);
  101. if start < 0 then
  102. start := 0;
  103. stop := round(center+ysupport);
  104. if stop >= tempimage.height then
  105. stop := tempimage.height-1;
  106. density := 0.0;
  107. maxcontribs := -1;
  108. for r := start to stop do
  109. begin
  110. dif := r - center;
  111. w := Filter (dif);
  112. if w > 0.0 then
  113. begin
  114. inc (maxcontribs);
  115. with contributions[maxcontribs] do
  116. begin
  117. weight := w;
  118. density := density + w;
  119. place := r;
  120. end;
  121. end;
  122. end;
  123. if (density <> 0.0) and (density <> 1.0) then
  124. begin
  125. density := 1.0 / density;
  126. for r := 0 to maxcontribs do
  127. contributions[r].weight := contributions[r].weight * density;
  128. end;
  129. for x := 0 to width-1 do
  130. begin
  131. gamma := 0.0;
  132. re := 0.0;
  133. gr := 0.0;
  134. bl := 0.0;
  135. for r := 0 to maxcontribs do
  136. with contributions[r] do
  137. with tempimage.colors[x,place] do
  138. begin
  139. a := weight * alpha / $FFFF;
  140. re := re + a * red;
  141. gr := gr + a * green;
  142. bl := bl + a * blue;
  143. gamma := gamma + a;
  144. end;
  145. with c do
  146. begin
  147. red := ColorRound (re);
  148. green := ColorRound (gr);
  149. blue := ColorRound (bl);
  150. alpha := ColorRound (gamma * $FFFF);
  151. end;
  152. canvas.colors[x+dx,y+dy] := c;
  153. end;
  154. end;
  155. end;
  156. procedure TFPBaseInterpolation.Execute(x, y, w, h: integer);
  157. var maxy : integer;
  158. rx,ry : integer;
  159. begin
  160. tempimage := TFPMemoryImage.Create (w,image.height);
  161. tempimage.UsePalette := false;
  162. xfactor := image.Width / w;
  163. yfactor := image.Height / h;
  164. if xfactor > 1.0 then
  165. xsupport := MaxSupport
  166. else
  167. xsupport := xfactor * MaxSupport;
  168. if yfactor > 1.0 then
  169. ysupport := MaxSupport
  170. else
  171. ysupport := yfactor * MaxSupport;
  172. Horizontal (w);
  173. Vertical (x,y,w,h);
  174. end;
  175. { TMitchelInterpolation }
  176. function TMitchelInterpolation.Filter(x: double): double;
  177. const
  178. B = (1.0/3.0);
  179. C = (1.0/3.0);
  180. P0 = (( 6.0- 2.0*B )/6.0);
  181. P2 = ((-18.0+12.0*B+ 6.0*C)/6.0);
  182. P3 = (( 12.0- 9.0*B- 6.0*C)/6.0);
  183. Q0 = (( 8.0*B+24.0*C)/6.0);
  184. Q1 = (( -12.0*B-48.0*C)/6.0);
  185. Q2 = (( 6.0*B+30.0*C)/6.0);
  186. Q3 = (( - 1.0*B- 6.0*C)/6.0);
  187. begin
  188. if (x < -2.0) then
  189. result := 0.0
  190. else if (x < -1.0) then
  191. result := Q0-x*(Q1-x*(Q2-x*Q3))
  192. else if (x < 0.0) then
  193. result := P0+x*x*(P2-x*P3)
  194. else if (x < 1.0) then
  195. result := P0+x*x*(P2+x*P3)
  196. else if (x < 2.0) then
  197. result := Q0+x*(Q1+x*(Q2+x*Q3))
  198. else
  199. result := 0.0;
  200. end;
  201. function TMitchelInterpolation.MaxSupport: double;
  202. begin
  203. result := 2.0;
  204. end;