GR32_Transforms.pas 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915
  1. unit GR32_Transforms;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Graphics32
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2009
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. * Andre Beckedorf <[email protected]>
  32. * Mattias Andersson <[email protected]>
  33. * J. Tulach <[email protected]>
  34. * Michael Hansen <[email protected]>
  35. * Peter Larson
  36. *
  37. * ***** END LICENSE BLOCK ***** *)
  38. interface
  39. {$I GR32.inc}
  40. uses
  41. System.Types,
  42. SysUtils, Classes, GR32, GR32_VectorMaps, GR32_Rasterizers;
  43. type
  44. ETransformError = class(Exception);
  45. ETransformNotImplemented = class(Exception);
  46. type
  47. TFloatMatrix = array [0..2, 0..2] of TFloat; // 3x3 TFloat precision
  48. TFixedMatrix = array [0..2, 0..2] of TFixed; // 3x3 fixed precision
  49. const
  50. IdentityMatrix: TFloatMatrix = (
  51. (1, 0, 0),
  52. (0, 1, 0),
  53. (0, 0, 1));
  54. type
  55. TVector3f = array [0..2] of TFloat;
  56. TVector3i = array [0..2] of Integer;
  57. // Matrix conversion routines
  58. function FixedMatrix(const FloatMatrix: TFloatMatrix): TFixedMatrix; overload;
  59. function FloatMatrix(const FixedMatrix: TFixedMatrix): TFloatMatrix; overload;
  60. procedure Adjoint(var M: TFloatMatrix);
  61. function Determinant(const M: TFloatMatrix): TFloat;
  62. procedure Scale(var M: TFloatMatrix; Factor: TFloat);
  63. procedure Invert(var M: TFloatMatrix);
  64. function Mult(const M1, M2: TFloatMatrix): TFloatMatrix;
  65. function VectorTransform(const M: TFloatMatrix; const V: TVector3f): TVector3f;
  66. type
  67. TTransformation = class(TNotifiablePersistent)
  68. private
  69. FSrcRect: TFloatRect;
  70. procedure SetSrcRect(const Value: TFloatRect);
  71. protected
  72. TransformValid: Boolean;
  73. procedure PrepareTransform; virtual;
  74. procedure ReverseTransformInt(DstX, DstY: Integer; out SrcX, SrcY: Integer); virtual;
  75. procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); virtual;
  76. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); virtual;
  77. procedure TransformInt(SrcX, SrcY: Integer; out DstX, DstY: Integer); virtual;
  78. procedure TransformFixed(SrcX, SrcY: TFixed; out DstX, DstY: TFixed); virtual;
  79. procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); virtual;
  80. public
  81. procedure Changed; override;
  82. function HasTransformedBounds: Boolean; virtual;
  83. function GetTransformedBounds: TFloatRect; overload;
  84. function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; overload; virtual;
  85. function ReverseTransform(const P: TPoint): TPoint; overload; virtual;
  86. function ReverseTransform(const P: TFixedPoint): TFixedPoint; overload; virtual;
  87. function ReverseTransform(const P: TFloatPoint): TFloatPoint; overload; virtual;
  88. function Transform(const P: TPoint): TPoint; overload; virtual;
  89. function Transform(const P: TFixedPoint): TFixedPoint; overload; virtual;
  90. function Transform(const P: TFloatPoint): TFloatPoint; overload; virtual;
  91. property SrcRect: TFloatRect read FSrcRect write SetSrcRect;
  92. end;
  93. TTransformationClass = class of TTransformation;
  94. TNestedTransformation = class(TTransformation)
  95. private
  96. FItems: TList;
  97. FOwner: TPersistent;
  98. function GetCount: Integer;
  99. function GetItem(Index: Integer): TTransformation;
  100. procedure SetItem(Index: Integer; const Value: TTransformation);
  101. protected
  102. procedure PrepareTransform; override;
  103. procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); override;
  104. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  105. procedure TransformFixed(SrcX, SrcY: TFixed; out DstX, DstY: TFixed); override;
  106. procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
  107. public
  108. constructor Create;
  109. destructor Destroy; override;
  110. function Add(ItemClass: TTransformationClass): TTransformation;
  111. procedure Clear;
  112. procedure Delete(Index: Integer);
  113. function Insert(Index: Integer; ItemClass: TTransformationClass): TTransformation;
  114. property Owner: TPersistent read FOwner;
  115. property Count: Integer read GetCount;
  116. property Items[Index: Integer]: TTransformation read GetItem write SetItem; default;
  117. end;
  118. T3x3Transformation = class(TTransformation)
  119. protected
  120. FMatrix, FInverseMatrix: TFloatMatrix;
  121. FFixedMatrix, FInverseFixedMatrix: TFixedMatrix;
  122. procedure PrepareTransform; override;
  123. procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); override;
  124. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  125. procedure TransformFixed(SrcX, SrcY: TFixed; out DstX, DstY: TFixed); override;
  126. procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
  127. public
  128. property Matrix: TFloatMatrix read FMatrix;
  129. end;
  130. TAffineTransformation = class(T3x3Transformation)
  131. private
  132. FStack: ^TFloatMatrix;
  133. FStackLevel: Integer;
  134. public
  135. constructor Create; virtual;
  136. function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
  137. procedure Push;
  138. procedure Pop;
  139. procedure Clear; overload;
  140. procedure Clear(BaseMatrix: TFloatMatrix); overload;
  141. procedure Rotate(Alpha: TFloat); overload; // degrees
  142. procedure Rotate(Cx, Cy, Alpha: TFloat); overload; // degrees
  143. procedure Skew(Fx, Fy: TFloat);
  144. procedure Scale(Sx, Sy: TFloat); overload;
  145. procedure Scale(Value: TFloat); overload;
  146. procedure Translate(Dx, Dy: TFloat);
  147. end;
  148. TProjectiveTransformation = class(T3x3Transformation)
  149. private
  150. FQuadX: array [0..3] of TFloat;
  151. FQuadY: array [0..3] of TFloat;
  152. procedure SetX0(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
  153. procedure SetX1(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
  154. procedure SetX2(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
  155. procedure SetX3(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
  156. procedure SetY0(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
  157. procedure SetY1(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
  158. procedure SetY2(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
  159. procedure SetY3(Value: TFloat); {$IFDEF UseInlining} inline; {$ENDIF}
  160. protected
  161. procedure PrepareTransform; override;
  162. procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); override;
  163. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  164. procedure TransformFixed(SrcX, SrcY: TFixed; out DstX, DstY: TFixed); override;
  165. procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
  166. public
  167. function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
  168. published
  169. property X0: TFloat read FQuadX[0] write SetX0;
  170. property X1: TFloat read FQuadX[1] write SetX1;
  171. property X2: TFloat read FQuadX[2] write SetX2;
  172. property X3: TFloat read FQuadX[3] write SetX3;
  173. property Y0: TFloat read FQuadY[0] write SetY0;
  174. property Y1: TFloat read FQuadY[1] write SetY1;
  175. property Y2: TFloat read FQuadY[2] write SetY2;
  176. property Y3: TFloat read FQuadY[3] write SetY3;
  177. end;
  178. TTwirlTransformation = class(TTransformation)
  179. private
  180. Frx, Fry: TFloat;
  181. FTwirl: TFloat;
  182. procedure SetTwirl(const Value: TFloat);
  183. protected
  184. procedure PrepareTransform; override;
  185. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  186. public
  187. constructor Create; virtual;
  188. function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
  189. published
  190. property Twirl: TFloat read FTwirl write SetTwirl;
  191. end;
  192. TBloatTransformation = class(TTransformation)
  193. private
  194. FBloatPower: TFloat;
  195. FBP: TFloat;
  196. FPiW, FPiH: TFloat;
  197. procedure SetBloatPower(const Value: TFloat);
  198. protected
  199. procedure PrepareTransform; override;
  200. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  201. procedure TransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  202. public
  203. constructor Create; virtual;
  204. published
  205. property BloatPower: TFloat read FBloatPower write SetBloatPower;
  206. end;
  207. TDisturbanceTransformation = class(TTransformation)
  208. private
  209. FDisturbance: TFloat;
  210. procedure SetDisturbance(const Value: TFloat);
  211. protected
  212. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  213. public
  214. function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
  215. published
  216. property Disturbance: TFloat read FDisturbance write SetDisturbance;
  217. end;
  218. TFishEyeTransformation = class(TTransformation)
  219. private
  220. Frx, Fry: TFloat;
  221. Faw, Fsr: TFloat;
  222. Sx, Sy: TFloat;
  223. FMinR: TFloat;
  224. protected
  225. procedure PrepareTransform; override;
  226. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  227. end;
  228. TPolarTransformation = class(TTransformation)
  229. private
  230. FDstRect: TFloatRect;
  231. FPhase: TFloat;
  232. Sx, Sy, Cx, Cy, Dx, Dy, Rt, Rt2, Rr, Rcx, Rcy: TFloat;
  233. procedure SetDstRect(const Value: TFloatRect);
  234. procedure SetPhase(const Value: TFloat);
  235. protected
  236. procedure PrepareTransform; override;
  237. procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
  238. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  239. public
  240. property DstRect: TFloatRect read FDstRect write SetDstRect;
  241. property Phase: TFloat read FPhase write SetPhase;
  242. end;
  243. TPathTransformation = class(TTransformation)
  244. private
  245. FTopLength: TFloat;
  246. FBottomLength: TFloat;
  247. FBottomCurve: TArrayOfFloatPoint;
  248. FTopCurve: TArrayOfFloatPoint;
  249. FTopHypot, FBottomHypot: array of record Dist, RecDist: TFloat end;
  250. procedure SetBottomCurve(const Value: TArrayOfFloatPoint);
  251. procedure SetTopCurve(const Value: TArrayOfFloatPoint);
  252. protected
  253. rdx, rdy: TFloat;
  254. procedure PrepareTransform; override;
  255. procedure TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat); override;
  256. public
  257. destructor Destroy; override;
  258. property TopCurve: TArrayOfFloatPoint read FTopCurve write SetTopCurve;
  259. property BottomCurve: TArrayOfFloatPoint read FBottomCurve write SetBottomCurve;
  260. end;
  261. TRemapTransformation = class(TTransformation)
  262. private
  263. FVectorMap : TVectorMap;
  264. FScalingFixed: TFixedVector;
  265. FScalingFloat: TFloatVector;
  266. FCombinedScalingFixed: TFixedVector;
  267. FCombinedScalingFloat: TFloatVector;
  268. FSrcTranslationFixed: TFixedVector;
  269. FSrcScaleFixed: TFixedVector;
  270. FDstTranslationFixed: TFixedVector;
  271. FDstScaleFixed: TFixedVector;
  272. FSrcTranslationFloat: TFloatVector;
  273. FSrcScaleFloat: TFloatVector;
  274. FDstTranslationFloat: TFloatVector;
  275. FDstScaleFloat: TFloatVector;
  276. FOffsetFixed : TFixedVector;
  277. FOffsetInt : TPoint;
  278. FMappingRect: TFloatRect;
  279. FOffset: TFloatVector;
  280. procedure SetMappingRect(Rect: TFloatRect);
  281. procedure SetOffset(const Value: TFloatVector);
  282. protected
  283. procedure PrepareTransform; override;
  284. procedure ReverseTransformInt(DstX, DstY: Integer; out SrcX, SrcY: Integer); override;
  285. procedure ReverseTransformFloat(DstX, DstY: TFloat; out SrcX, SrcY: TFloat); override;
  286. procedure ReverseTransformFixed(DstX, DstY: TFixed; out SrcX, SrcY: TFixed); override;
  287. public
  288. constructor Create; virtual;
  289. destructor Destroy; override;
  290. function HasTransformedBounds: Boolean; override;
  291. function GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect; override;
  292. procedure Scale(Sx, Sy: TFloat);
  293. property MappingRect: TFloatRect read FMappingRect write SetMappingRect;
  294. property Offset: TFloatVector read FOffset write SetOffset;
  295. property VectorMap: TVectorMap read FVectorMap write FVectorMap;
  296. end;
  297. function TransformPoints(Points: TArrayOfArrayOfFixedPoint; Transformation: TTransformation): TArrayOfArrayOfFixedPoint;
  298. procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation); overload;
  299. procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
  300. const DstClip: TRect); overload;
  301. procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
  302. Rasterizer: TRasterizer); overload;
  303. procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
  304. Rasterizer: TRasterizer; const DstClip: TRect); overload;
  305. procedure RasterizeTransformation(Vectormap: TVectormap;
  306. Transformation: TTransformation; DstRect: TRect;
  307. CombineMode: TVectorCombineMode = vcmAdd;
  308. CombineCallback: TVectorCombineEvent = nil);
  309. procedure SetBorderTransparent(ABitmap: TCustomBitmap32; ARect: TRect);
  310. { FullEdge controls how the bitmap is resampled }
  311. var
  312. FullEdge: Boolean = True;
  313. resourcestring
  314. RCStrReverseTransformationNotImplemented = 'Reverse transformation is not implemented in %s.';
  315. RCStrForwardTransformationNotImplemented = 'Forward transformation is not implemented in %s.';
  316. RCStrTopBottomCurveNil = 'Top or bottom curve is nil';
  317. implementation
  318. uses
  319. Math, GR32_Blend, GR32_LowLevel, GR32_Math, GR32_Bindings,
  320. GR32_Resamplers;
  321. resourcestring
  322. RCStrSrcRectIsEmpty = 'SrcRect is empty!';
  323. RCStrMappingRectIsEmpty = 'MappingRect is empty!';
  324. RStrStackEmpty = 'Stack empty';
  325. type
  326. {provides access to proctected members of TCustomBitmap32 by typecasting}
  327. TTransformationAccess = class(TTransformation);
  328. var
  329. DET32: function(a1, a2, b1, b2: Single): Single;
  330. DET64: function(a1, a2, b1, b2: Double): Double;
  331. { A bit of linear algebra }
  332. function DET32_Pas(a1, a2, b1, b2: Single): Single; overload;
  333. begin
  334. Result := a1 * b2 - a2 * b1;
  335. end;
  336. function DET64_Pas(a1, a2, b1, b2: Double): Double; overload;
  337. begin
  338. Result := a1 * b2 - a2 * b1;
  339. end;
  340. {$IFNDEF PUREPASCAL}
  341. function DET32_ASM(a1, a2, b1, b2: Single): Single; overload;
  342. asm
  343. {$IFDEF CPU64}
  344. MULSS XMM0, XMM3
  345. MULSS XMM1, XMM2
  346. ADDSS XMM0, XMM1
  347. {$ELSE}
  348. FLD A1.Single
  349. FMUL B2.Single
  350. FLD A2.Single
  351. FMUL B1.Single
  352. FSUBP
  353. {$ENDIF}
  354. end;
  355. function DET64_ASM(a1, a2, b1, b2: Double): Double; overload;
  356. asm
  357. {$IFDEF CPU64}
  358. MULSD XMM0, XMM3
  359. MULSD XMM1, XMM2
  360. ADDSD XMM0, XMM1
  361. {$ELSE}
  362. FLD A1.Double
  363. FMUL B2.Double
  364. FLD A2.Double
  365. FMUL B1.Double
  366. FSUBP
  367. {$ENDIF}
  368. end;
  369. {$ENDIF}
  370. { implementation of detereminant for TFloat precision }
  371. function _DET(a1, a2, b1, b2: TFloat): TFloat; overload; {$IFDEF UseInlining} inline; {$ENDIF}
  372. begin
  373. Result := a1 * b2 - a2 * b1;
  374. end;
  375. function _DET(a1, a2, a3, b1, b2, b3, c1, c2, c3: TFloat): TFloat; overload; {$IFDEF UseInlining} inline; {$ENDIF}
  376. begin
  377. Result :=
  378. a1 * (b2 * c3 - b3 * c2) -
  379. b1 * (a2 * c3 - a3 * c2) +
  380. c1 * (a2 * b3 - a3 * b2);
  381. end;
  382. procedure Adjoint(var M: TFloatMatrix);
  383. var
  384. Tmp: TFloatMatrix;
  385. begin
  386. Tmp := M;
  387. M[0,0] := _DET(Tmp[1,1], Tmp[1,2], Tmp[2,1], Tmp[2,2]);
  388. M[0,1] := -_DET(Tmp[0,1], Tmp[0,2], Tmp[2,1], Tmp[2,2]);
  389. M[0,2] := _DET(Tmp[0,1], Tmp[0,2], Tmp[1,1], Tmp[1,2]);
  390. M[1,0] := -_DET(Tmp[1,0], Tmp[1,2], Tmp[2,0], Tmp[2,2]);
  391. M[1,1] := _DET(Tmp[0,0], Tmp[0,2], Tmp[2,0], Tmp[2,2]);
  392. M[1,2] := -_DET(Tmp[0,0], Tmp[0,2], Tmp[1,0], Tmp[1,2]);
  393. M[2,0] := _DET(Tmp[1,0], Tmp[1,1], Tmp[2,0], Tmp[2,1]);
  394. M[2,1] := -_DET(Tmp[0,0], Tmp[0,1], Tmp[2,0], Tmp[2,1]);
  395. M[2,2] := _DET(Tmp[0,0], Tmp[0,1], Tmp[1,0], Tmp[1,1]);
  396. end;
  397. function Determinant(const M: TFloatMatrix): TFloat;
  398. begin
  399. Result := _DET(M[0,0], M[1,0], M[2,0],
  400. M[0,1], M[1,1], M[2,1],
  401. M[0,2], M[1,2], M[2,2]);
  402. end;
  403. procedure Scale(var M: TFloatMatrix; Factor: TFloat);
  404. var
  405. i, j: Integer;
  406. begin
  407. for i := 0 to 2 do
  408. for j := 0 to 2 do
  409. M[i,j] := M[i,j] * Factor;
  410. end;
  411. procedure Invert(var M: TFloatMatrix);
  412. var
  413. Det: TFloat;
  414. begin
  415. Det := Determinant(M);
  416. if Abs(Det) < 1E-5 then M := IdentityMatrix
  417. else
  418. begin
  419. Adjoint(M);
  420. Scale(M, 1 / Det);
  421. end;
  422. end;
  423. function Mult(const M1, M2: TFloatMatrix): TFloatMatrix;
  424. var
  425. i, j: Integer;
  426. begin
  427. for i := 0 to 2 do
  428. for j := 0 to 2 do
  429. Result[i, j] :=
  430. M1[0, j] * M2[i, 0] +
  431. M1[1, j] * M2[i, 1] +
  432. M1[2, j] * M2[i, 2];
  433. end;
  434. function VectorTransform(const M: TFloatMatrix; const V: TVector3f): TVector3f;
  435. begin
  436. Result[0] := M[0,0] * V[0] + M[1,0] * V[1] + M[2,0] * V[2];
  437. Result[1] := M[0,1] * V[0] + M[1,1] * V[1] + M[2,1] * V[2];
  438. Result[2] := M[0,2] * V[0] + M[1,2] * V[1] + M[2,2] * V[2];
  439. end;
  440. { Transformation functions }
  441. function TransformPoints(Points: TArrayOfArrayOfFixedPoint; Transformation: TTransformation): TArrayOfArrayOfFixedPoint;
  442. var
  443. I, J: Integer;
  444. begin
  445. if Points = nil then
  446. Result := nil
  447. else
  448. begin
  449. SetLength(Result, Length(Points));
  450. Transformation.PrepareTransform;
  451. for I := 0 to High(Result) do
  452. begin
  453. SetLength(Result[I], Length(Points[I]));
  454. if Length(Result[I]) > 0 then
  455. for J := 0 to High(Result[I]) do
  456. Transformation.TransformFixed(Points[I][J].X, Points[I][J].Y, Result[I][J].X, Result[I][J].Y);
  457. end;
  458. end;
  459. end;
  460. procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation);
  461. var
  462. Rasterizer: TRasterizer;
  463. begin
  464. Rasterizer := DefaultRasterizerClass.Create;
  465. try
  466. Transform(Dst, Src, Transformation, Rasterizer);
  467. finally
  468. Rasterizer.Free;
  469. end;
  470. end;
  471. procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation; const DstClip: TRect);
  472. var
  473. Rasterizer: TRasterizer;
  474. begin
  475. Rasterizer := DefaultRasterizerClass.Create;
  476. try
  477. Transform(Dst, Src, Transformation, Rasterizer, DstClip);
  478. finally
  479. Rasterizer.Free;
  480. end;
  481. end;
  482. procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
  483. Rasterizer: TRasterizer);
  484. begin
  485. Transform(Dst, Src, Transformation, Rasterizer, Dst.BoundsRect);
  486. end;
  487. procedure Transform(Dst, Src: TCustomBitmap32; Transformation: TTransformation;
  488. Rasterizer: TRasterizer; const DstClip: TRect);
  489. var
  490. DstRect: TRect;
  491. Transformer: TTransformer;
  492. begin
  493. GR32.IntersectRect(DstRect, DstClip, Dst.ClipRect);
  494. if (DstRect.Right < DstRect.Left) or (DstRect.Bottom < DstRect.Top) then Exit;
  495. if not Dst.MeasuringMode then
  496. begin
  497. Transformer := TTransformer.Create(Src.Resampler, Transformation);
  498. try
  499. Rasterizer.Sampler := Transformer;
  500. Rasterizer.Rasterize(Dst, DstRect, Src);
  501. finally
  502. EMMS;
  503. Transformer.Free;
  504. end;
  505. end;
  506. Dst.Changed(DstRect);
  507. end;
  508. procedure SetBorderTransparent(ABitmap: TCustomBitmap32; ARect: TRect);
  509. var
  510. I: Integer;
  511. begin
  512. GR32.IntersectRect(ARect, ARect, ABitmap.BoundsRect);
  513. with ARect, ABitmap do
  514. if (Right > Left) and (Bottom > Top) and
  515. (Left < ClipRect.Right) and (Top < ClipRect.Bottom) and
  516. (Right > ClipRect.Left) and (Bottom > ClipRect.Top) then
  517. begin
  518. Dec(Right);
  519. Dec(Bottom);
  520. for I := Left to Right do
  521. begin
  522. ABitmap[I, Top] := ABitmap[I, Top] and $00FFFFFF;
  523. ABitmap[I, Bottom] := ABitmap[I, Bottom] and $00FFFFFF;
  524. end;
  525. for I := Top to Bottom do
  526. begin
  527. ABitmap[Left, I] := ABitmap[Left, I] and $00FFFFFF;
  528. ABitmap[Right, I] := ABitmap[Right, I] and $00FFFFFF;
  529. end;
  530. Changed;
  531. end;
  532. end;
  533. { TTransformation }
  534. function TTransformation.GetTransformedBounds: TFloatRect;
  535. begin
  536. Result := GetTransformedBounds(FSrcRect);
  537. end;
  538. procedure TTransformation.Changed;
  539. begin
  540. TransformValid := False;
  541. inherited;
  542. end;
  543. function TTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
  544. begin
  545. Result := ASrcRect;
  546. end;
  547. function TTransformation.HasTransformedBounds: Boolean;
  548. begin
  549. Result := True;
  550. end;
  551. procedure TTransformation.PrepareTransform;
  552. begin
  553. // Dummy
  554. end;
  555. function TTransformation.ReverseTransform(const P: TFloatPoint): TFloatPoint;
  556. begin
  557. if not TransformValid then PrepareTransform;
  558. ReverseTransformFloat(P.X, P.Y, Result.X, Result.Y);
  559. end;
  560. function TTransformation.ReverseTransform(const P: TFixedPoint): TFixedPoint;
  561. begin
  562. if not TransformValid then PrepareTransform;
  563. ReverseTransformFixed(P.X, P.Y, Result.X, Result.Y);
  564. end;
  565. function TTransformation.ReverseTransform(const P: TPoint): TPoint;
  566. begin
  567. if not TransformValid then PrepareTransform;
  568. ReverseTransformInt(P.X, P.Y, Result.X, Result.Y);
  569. end;
  570. procedure TTransformation.ReverseTransformFixed(DstX, DstY: TFixed;
  571. out SrcX, SrcY: TFixed);
  572. var
  573. X, Y: TFloat;
  574. begin
  575. ReverseTransformFloat(DstX * FixedToFloat, DstY * FixedToFloat, X, Y);
  576. SrcX := Fixed(X);
  577. SrcY := Fixed(Y);
  578. end;
  579. procedure TTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
  580. out SrcX, SrcY: TFloat);
  581. begin
  582. // ReverseTransformFloat is the top precisionlevel, all decendants must override at least this level!
  583. raise ETransformNotImplemented.CreateFmt(RCStrReverseTransformationNotImplemented, [Self.Classname]);
  584. end;
  585. procedure TTransformation.ReverseTransformInt(DstX, DstY: Integer;
  586. out SrcX, SrcY: Integer);
  587. var
  588. X, Y: TFixed;
  589. begin
  590. ReverseTransformFixed(DstX shl 16, DstY shl 16, X, Y);
  591. SrcX := FixedRound(X);
  592. SrcY := FixedRound(Y);
  593. end;
  594. procedure TTransformation.SetSrcRect(const Value: TFloatRect);
  595. begin
  596. FSrcRect := Value;
  597. Changed;
  598. end;
  599. function TTransformation.Transform(const P: TFloatPoint): TFloatPoint;
  600. begin
  601. if not TransformValid then PrepareTransform;
  602. TransformFloat(P.X, P.Y, Result.X, Result.Y);
  603. end;
  604. function TTransformation.Transform(const P: TFixedPoint): TFixedPoint;
  605. begin
  606. if not TransformValid then PrepareTransform;
  607. TransformFixed(P.X, P.Y, Result.X, Result.Y);
  608. end;
  609. function TTransformation.Transform(const P: TPoint): TPoint;
  610. begin
  611. if not TransformValid then PrepareTransform;
  612. TransformInt(P.X, P.Y, Result.X, Result.Y);
  613. end;
  614. procedure TTransformation.TransformFixed(SrcX, SrcY: TFixed; out DstX,
  615. DstY: TFixed);
  616. var
  617. X, Y: TFloat;
  618. begin
  619. TransformFloat(SrcX * FixedToFloat, SrcY * FixedToFloat, X, Y);
  620. DstX := Fixed(X);
  621. DstY := Fixed(Y);
  622. end;
  623. procedure TTransformation.TransformFloat(SrcX, SrcY: TFloat; out DstX, DstY: TFloat);
  624. begin
  625. // TransformFloat is the top precisionlevel, all decendants must override at least this level!
  626. raise ETransformNotImplemented.CreateFmt(RCStrForwardTransformationNotImplemented, [Self.Classname]);
  627. end;
  628. procedure TTransformation.TransformInt(SrcX, SrcY: Integer; out DstX, DstY: Integer);
  629. var
  630. X, Y: TFixed;
  631. begin
  632. TransformFixed(SrcX shl 16, SrcY shl 16, X, Y);
  633. DstX := FixedRound(X);
  634. DstY := FixedRound(Y);
  635. end;
  636. { TNestedTransformation }
  637. constructor TNestedTransformation.Create;
  638. begin
  639. FItems := TList.Create;
  640. end;
  641. destructor TNestedTransformation.Destroy;
  642. begin
  643. if Assigned(FItems) then Clear;
  644. FItems.Free;
  645. inherited;
  646. end;
  647. function TNestedTransformation.Add(
  648. ItemClass: TTransformationClass): TTransformation;
  649. begin
  650. Result := ItemClass.Create;
  651. FItems.Add(Result);
  652. end;
  653. procedure TNestedTransformation.Clear;
  654. begin
  655. BeginUpdate;
  656. try
  657. while FItems.Count > 0 do
  658. Delete(FItems.Count - 1);
  659. finally
  660. EndUpdate;
  661. end;
  662. end;
  663. procedure TNestedTransformation.Delete(Index: Integer);
  664. begin
  665. TTransformation(FItems[Index]).Free;
  666. FItems.Delete(Index);
  667. end;
  668. function TNestedTransformation.GetCount: Integer;
  669. begin
  670. Result := FItems.Count;
  671. end;
  672. function TNestedTransformation.GetItem(Index: Integer): TTransformation;
  673. begin
  674. Result := FItems[Index];
  675. end;
  676. function TNestedTransformation.Insert(Index: Integer;
  677. ItemClass: TTransformationClass): TTransformation;
  678. begin
  679. BeginUpdate;
  680. try
  681. Result := Add(ItemClass);
  682. finally
  683. EndUpdate;
  684. end;
  685. end;
  686. procedure TNestedTransformation.PrepareTransform;
  687. var
  688. Index: Integer;
  689. begin
  690. for Index := 0 to Count - 1 do
  691. TTransformation(FItems[Index]).PrepareTransform;
  692. end;
  693. procedure TNestedTransformation.ReverseTransformFixed(DstX, DstY: TFixed;
  694. out SrcX, SrcY: TFixed);
  695. var
  696. Index: Integer;
  697. begin
  698. for Index := 0 to Count - 1 do
  699. begin
  700. TTransformation(FItems[Index]).ReverseTransformFixed(DstX, DstY, SrcX,
  701. SrcY);
  702. DstX := SrcX;
  703. DstY := SrcY;
  704. end;
  705. end;
  706. procedure TNestedTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
  707. out SrcX, SrcY: TFloat);
  708. var
  709. Index: Integer;
  710. begin
  711. for Index := 0 to Count - 1 do
  712. begin
  713. TTransformation(FItems[Index]).ReverseTransformFloat(DstX, DstY, SrcX,
  714. SrcY);
  715. DstX := SrcX;
  716. DstY := SrcY;
  717. end;
  718. end;
  719. procedure TNestedTransformation.SetItem(Index: Integer;
  720. const Value: TTransformation);
  721. begin
  722. TCollectionItem(FItems[Index]).Assign(Value);
  723. end;
  724. procedure TNestedTransformation.TransformFixed(SrcX, SrcY: TFixed; out DstX,
  725. DstY: TFixed);
  726. var
  727. Index: Integer;
  728. begin
  729. for Index := 0 to Count - 1 do
  730. begin
  731. TTransformation(FItems[Index]).TransformFixed(SrcX, SrcY, DstX, DstY);
  732. SrcX := DstX;
  733. SrcY := DstY;
  734. end;
  735. end;
  736. procedure TNestedTransformation.TransformFloat(SrcX, SrcY: TFloat; out DstX,
  737. DstY: TFloat);
  738. var
  739. Index: Integer;
  740. begin
  741. for Index := 0 to Count - 1 do
  742. begin
  743. TTransformation(FItems[Index]).TransformFloat(SrcX, SrcY, DstX, DstY);
  744. SrcX := DstX;
  745. SrcY := DstY;
  746. end;
  747. end;
  748. { T3x3Transformation }
  749. procedure T3x3Transformation.PrepareTransform;
  750. begin
  751. FInverseMatrix := Matrix;
  752. Invert(FInverseMatrix);
  753. // calculate a fixed point (65536) factors
  754. FInverseFixedMatrix := FixedMatrix(FInverseMatrix);
  755. FFixedMatrix := FixedMatrix(Matrix);
  756. TransformValid := True;
  757. end;
  758. procedure T3x3Transformation.ReverseTransformFixed(DstX, DstY: TFixed; out SrcX,
  759. SrcY: TFixed);
  760. begin
  761. SrcX := FixedMul(DstX, FInverseFixedMatrix[0, 0]) +
  762. FixedMul(DstY, FInverseFixedMatrix[1, 0]) + FInverseFixedMatrix[2, 0];
  763. SrcY := FixedMul(DstX, FInverseFixedMatrix[0, 1]) +
  764. FixedMul(DstY, FInverseFixedMatrix[1, 1]) + FInverseFixedMatrix[2, 1];
  765. end;
  766. procedure T3x3Transformation.ReverseTransformFloat(DstX, DstY: TFloat; out SrcX,
  767. SrcY: TFloat);
  768. begin
  769. SrcX := DstX * FInverseMatrix[0, 0] + DstY * FInverseMatrix[1, 0] +
  770. FInverseMatrix[2, 0];
  771. SrcY := DstX * FInverseMatrix[0, 1] + DstY * FInverseMatrix[1, 1] +
  772. FInverseMatrix[2, 1];
  773. end;
  774. procedure T3x3Transformation.TransformFixed(SrcX, SrcY: TFixed; out DstX,
  775. DstY: TFixed);
  776. begin
  777. DstX := FixedMul(SrcX, FFixedMatrix[0, 0]) +
  778. FixedMul(SrcY, FFixedMatrix[1, 0]) + FFixedMatrix[2, 0];
  779. DstY := FixedMul(SrcX, FFixedMatrix[0, 1]) +
  780. FixedMul(SrcY, FFixedMatrix[1, 1]) + FFixedMatrix[2, 1];
  781. end;
  782. procedure T3x3Transformation.TransformFloat(SrcX, SrcY: TFloat; out DstX,
  783. DstY: TFloat);
  784. begin
  785. DstX := SrcX * Matrix[0, 0] + SrcY * Matrix[1, 0] + Matrix[2, 0];
  786. DstY := SrcX * Matrix[0, 1] + SrcY * Matrix[1, 1] + Matrix[2, 1];
  787. end;
  788. { TAffineTransformation }
  789. constructor TAffineTransformation.Create;
  790. begin
  791. FStackLevel := 0;
  792. FStack := nil;
  793. Clear;
  794. end;
  795. procedure TAffineTransformation.Clear;
  796. begin
  797. FMatrix := IdentityMatrix;
  798. Changed;
  799. end;
  800. procedure TAffineTransformation.Clear(BaseMatrix: TFloatMatrix);
  801. begin
  802. FMatrix := BaseMatrix;
  803. Changed;
  804. end;
  805. function TAffineTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
  806. var
  807. V1, V2, V3, V4: TVector3f;
  808. begin
  809. V1[0] := ASrcRect.Left; V1[1] := ASrcRect.Top; V1[2] := 1;
  810. V2[0] := ASrcRect.Right; V2[1] := V1[1]; V2[2] := 1;
  811. V3[0] := V1[0]; V3[1] := ASrcRect.Bottom; V3[2] := 1;
  812. V4[0] := V2[0]; V4[1] := V3[1]; V4[2] := 1;
  813. V1 := VectorTransform(Matrix, V1);
  814. V2 := VectorTransform(Matrix, V2);
  815. V3 := VectorTransform(Matrix, V3);
  816. V4 := VectorTransform(Matrix, V4);
  817. Result.Left := Min(Min(V1[0], V2[0]), Min(V3[0], V4[0]));
  818. Result.Right := Max(Max(V1[0], V2[0]), Max(V3[0], V4[0]));
  819. Result.Top := Min(Min(V1[1], V2[1]), Min(V3[1], V4[1]));
  820. Result.Bottom := Max(Max(V1[1], V2[1]), Max(V3[1], V4[1]));
  821. end;
  822. procedure TAffineTransformation.Push;
  823. begin
  824. Inc(FStackLevel);
  825. ReallocMem(FStack, FStackLevel * SizeOf(TFloatMatrix));
  826. Move(FMatrix, FStack^[FStackLevel - 1], SizeOf(TFloatMatrix));
  827. end;
  828. procedure TAffineTransformation.Pop;
  829. begin
  830. if FStackLevel <= 0 then
  831. raise Exception.Create(RStrStackEmpty);
  832. Move(FStack^[FStackLevel - 1], FMatrix, SizeOf(TFloatMatrix));
  833. Dec(FStackLevel);
  834. Changed;
  835. end;
  836. procedure TAffineTransformation.Rotate(Alpha: TFloat);
  837. var
  838. S, C: TFloat;
  839. M: TFloatMatrix;
  840. begin
  841. Alpha := DegToRad(Alpha);
  842. GR32_Math.SinCos(Alpha, S, C);
  843. M := IdentityMatrix;
  844. M[0, 0] := C; M[1, 0] := S;
  845. M[0, 1] := -S; M[1, 1] := C;
  846. FMatrix := Mult(M, Matrix);
  847. Changed;
  848. end;
  849. procedure TAffineTransformation.Rotate(Cx, Cy, Alpha: TFloat);
  850. var
  851. S, C: TFloat;
  852. M: TFloatMatrix;
  853. begin
  854. if (Cx <> 0) or (Cy <> 0) then Translate(-Cx, -Cy);
  855. Alpha := DegToRad(Alpha);
  856. GR32_Math.SinCos(Alpha, S, C);
  857. M := IdentityMatrix;
  858. M[0, 0] := C; M[1, 0] := S;
  859. M[0, 1] := -S; M[1, 1] := C;
  860. FMatrix := Mult(M, Matrix);
  861. if (Cx <> 0) or (Cy <> 0) then Translate(Cx, Cy);
  862. Changed;
  863. end;
  864. procedure TAffineTransformation.Scale(Sx, Sy: TFloat);
  865. var
  866. M: TFloatMatrix;
  867. begin
  868. M := IdentityMatrix;
  869. M[0, 0] := Sx;
  870. M[1, 1] := Sy;
  871. FMatrix := Mult(M, Matrix);
  872. Changed;
  873. end;
  874. procedure TAffineTransformation.Scale(Value: TFloat);
  875. var
  876. M: TFloatMatrix;
  877. begin
  878. M := IdentityMatrix;
  879. M[0, 0] := Value;
  880. M[1, 1] := Value;
  881. FMatrix := Mult(M, Matrix);
  882. Changed;
  883. end;
  884. procedure TAffineTransformation.Skew(Fx, Fy: TFloat);
  885. var
  886. M: TFloatMatrix;
  887. begin
  888. M := IdentityMatrix;
  889. M[1, 0] := Fx;
  890. M[0, 1] := Fy;
  891. FMatrix := Mult(M, Matrix);
  892. Changed;
  893. end;
  894. procedure TAffineTransformation.Translate(Dx, Dy: TFloat);
  895. var
  896. M: TFloatMatrix;
  897. begin
  898. M := IdentityMatrix;
  899. M[2, 0] := Dx;
  900. M[2, 1] := Dy;
  901. FMatrix := Mult(M, Matrix);
  902. Changed;
  903. end;
  904. { TProjectiveTransformation }
  905. function TProjectiveTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
  906. begin
  907. Result.Left := Min(Min(FQuadX[0], FQuadX[1]), Min(FQuadX[2], FQuadX[3]));
  908. Result.Right := Max(Max(FQuadX[0], FQuadX[1]), Max(FQuadX[2], FQuadX[3]));
  909. Result.Top := Min(Min(FQuadY[0], FQuadY[1]), Min(FQuadY[2], FQuadY[3]));
  910. Result.Bottom := Max(Max(FQuadY[0], FQuadY[1]), Max(FQuadY[2], FQuadY[3]));
  911. end;
  912. procedure TProjectiveTransformation.PrepareTransform;
  913. var
  914. dx1, dx2, px, dy1, dy2, py: TFloat;
  915. g, h, k: TFloat;
  916. R: TFloatMatrix;
  917. begin
  918. px := FQuadX[0] - FQuadX[1] + FQuadX[2] - FQuadX[3];
  919. py := FQuadY[0] - FQuadY[1] + FQuadY[2] - FQuadY[3];
  920. if (px = 0) and (py = 0) then
  921. begin
  922. // affine mapping
  923. FMatrix[0, 0] := FQuadX[1] - FQuadX[0];
  924. FMatrix[1, 0] := FQuadX[2] - FQuadX[1];
  925. FMatrix[2, 0] := FQuadX[0];
  926. FMatrix[0, 1] := FQuadY[1] - FQuadY[0];
  927. FMatrix[1, 1] := FQuadY[2] - FQuadY[1];
  928. FMatrix[2, 1] := FQuadY[0];
  929. FMatrix[0, 2] := 0;
  930. FMatrix[1, 2] := 0;
  931. FMatrix[2, 2] := 1;
  932. end
  933. else
  934. begin
  935. // projective mapping
  936. dx1 := FQuadX[1] - FQuadX[2];
  937. dx2 := FQuadX[3] - FQuadX[2];
  938. dy1 := FQuadY[1] - FQuadY[2];
  939. dy2 := FQuadY[3] - FQuadY[2];
  940. k := dx1 * dy2 - dx2 * dy1;
  941. if k <> 0 then
  942. begin
  943. k := 1 / k;
  944. g := (px * dy2 - py * dx2) * k;
  945. h := (dx1 * py - dy1 * px) * k;
  946. FMatrix[0, 0] := FQuadX[1] - FQuadX[0] + g * FQuadX[1];
  947. FMatrix[1, 0] := FQuadX[3] - FQuadX[0] + h * FQuadX[3];
  948. FMatrix[2, 0] := FQuadX[0];
  949. FMatrix[0, 1] := FQuadY[1] - FQuadY[0] + g * FQuadY[1];
  950. FMatrix[1, 1] := FQuadY[3] - FQuadY[0] + h * FQuadY[3];
  951. FMatrix[2, 1] := FQuadY[0];
  952. FMatrix[0, 2] := g;
  953. FMatrix[1, 2] := h;
  954. FMatrix[2, 2] := 1;
  955. end
  956. else
  957. begin
  958. FillChar(FMatrix, SizeOf(FMatrix), 0);
  959. end;
  960. end;
  961. // denormalize texture space (u, v)
  962. R := IdentityMatrix;
  963. R[0, 0] := 1 / (SrcRect.Right - SrcRect.Left);
  964. R[1, 1] := 1 / (SrcRect.Bottom - SrcRect.Top);
  965. FMatrix := Mult(FMatrix, R);
  966. R := IdentityMatrix;
  967. R[2, 0] := -SrcRect.Left;
  968. R[2, 1] := -SrcRect.Top;
  969. FMatrix := Mult(FMatrix, R);
  970. inherited;
  971. end;
  972. procedure TProjectiveTransformation.SetX0(Value: TFloat);
  973. begin
  974. FQuadX[0] := Value;
  975. Changed;
  976. end;
  977. procedure TProjectiveTransformation.SetX1(Value: TFloat);
  978. begin
  979. FQuadX[1] := Value;
  980. Changed;
  981. end;
  982. procedure TProjectiveTransformation.SetX2(Value: TFloat);
  983. begin
  984. FQuadX[2] := Value;
  985. Changed;
  986. end;
  987. procedure TProjectiveTransformation.SetX3(Value: TFloat);
  988. begin
  989. FQuadX[3] := Value;
  990. Changed;
  991. end;
  992. procedure TProjectiveTransformation.SetY0(Value: TFloat);
  993. begin
  994. FQuadY[0] := Value;
  995. Changed;
  996. end;
  997. procedure TProjectiveTransformation.SetY1(Value: TFloat);
  998. begin
  999. FQuadY[1] := Value;
  1000. Changed;
  1001. end;
  1002. procedure TProjectiveTransformation.SetY2(Value: TFloat);
  1003. begin
  1004. FQuadY[2] := Value;
  1005. Changed;
  1006. end;
  1007. procedure TProjectiveTransformation.SetY3(Value: TFloat);
  1008. begin
  1009. FQuadY[3] := Value;
  1010. Changed;
  1011. end;
  1012. procedure TProjectiveTransformation.ReverseTransformFixed(DstX, DstY: TFixed;
  1013. out SrcX, SrcY: TFixed);
  1014. var
  1015. Z: TFixed;
  1016. Zf: TFloat;
  1017. begin
  1018. Z := FixedMul(FInverseFixedMatrix[0, 2], DstX) +
  1019. FixedMul(FInverseFixedMatrix[1, 2], DstY) + FInverseFixedMatrix[2, 2];
  1020. if Z = 0 then Exit;
  1021. {$IFDEF UseInlining}
  1022. SrcX := FixedMul(DstX, FInverseFixedMatrix[0, 0]) +
  1023. FixedMul(DstY, FInverseFixedMatrix[1, 0]) + FInverseFixedMatrix[2, 0];
  1024. SrcY := FixedMul(DstX, FInverseFixedMatrix[0,1]) +
  1025. FixedMul(DstY, FInverseFixedMatrix[1, 1]) + FInverseFixedMatrix[2, 1];
  1026. {$ELSE}
  1027. inherited;
  1028. {$ENDIF}
  1029. if Z <> FixedOne then
  1030. begin
  1031. EMMS;
  1032. Zf := FixedOne / Z;
  1033. SrcX := Round(SrcX * Zf);
  1034. SrcY := Round(SrcY * Zf);
  1035. end;
  1036. end;
  1037. procedure TProjectiveTransformation.ReverseTransformFloat(
  1038. DstX, DstY: TFloat;
  1039. out SrcX, SrcY: TFloat);
  1040. var
  1041. Z: TFloat;
  1042. begin
  1043. EMMS;
  1044. Z := FInverseMatrix[0, 2] * DstX + FInverseMatrix[1, 2] * DstY +
  1045. FInverseMatrix[2, 2];
  1046. if Z = 0 then Exit;
  1047. {$IFDEF UseInlining}
  1048. SrcX := DstX * FInverseMatrix[0, 0] + DstY * FInverseMatrix[1, 0] +
  1049. FInverseMatrix[2, 0];
  1050. SrcY := DstX * FInverseMatrix[0, 1] + DstY * FInverseMatrix[1, 1] +
  1051. FInverseMatrix[2, 1];
  1052. {$ELSE}
  1053. inherited;
  1054. {$ENDIF}
  1055. if Z <> 1 then
  1056. begin
  1057. Z := 1 / Z;
  1058. SrcX := SrcX * Z;
  1059. SrcY := SrcY * Z;
  1060. end;
  1061. end;
  1062. procedure TProjectiveTransformation.TransformFixed(SrcX, SrcY: TFixed;
  1063. out DstX, DstY: TFixed);
  1064. var
  1065. Z: TFixed;
  1066. Zf: TFloat;
  1067. begin
  1068. Z := FixedMul(FFixedMatrix[0, 2], SrcX) +
  1069. FixedMul(FFixedMatrix[1, 2], SrcY) + FFixedMatrix[2, 2];
  1070. if Z = 0 then Exit;
  1071. {$IFDEF UseInlining}
  1072. DstX := FixedMul(SrcX, FFixedMatrix[0, 0]) +
  1073. FixedMul(SrcY, FFixedMatrix[1, 0]) + FFixedMatrix[2, 0];
  1074. DstY := FixedMul(SrcX, FFixedMatrix[0, 1]) +
  1075. FixedMul(SrcY, FFixedMatrix[1, 1]) + FFixedMatrix[2, 1];
  1076. {$ELSE}
  1077. inherited;
  1078. {$ENDIF}
  1079. if Z <> FixedOne then
  1080. begin
  1081. EMMS;
  1082. Zf := FixedOne / Z;
  1083. DstX := Round(DstX * Zf);
  1084. DstY := Round(DstY * Zf);
  1085. end;
  1086. end;
  1087. procedure TProjectiveTransformation.TransformFloat(SrcX, SrcY: TFloat;
  1088. out DstX, DstY: TFloat);
  1089. var
  1090. Z: TFloat;
  1091. begin
  1092. EMMS;
  1093. Z := FMatrix[0, 2] * SrcX + FMatrix[1, 2] * SrcY + FMatrix[2, 2];
  1094. if Z = 0 then Exit;
  1095. {$IFDEF UseInlining}
  1096. DstX := SrcX * Matrix[0, 0] + SrcY * Matrix[1, 0] + Matrix[2, 0];
  1097. DstY := SrcX * Matrix[0, 1] + SrcY * Matrix[1, 1] + Matrix[2, 1];
  1098. {$ELSE}
  1099. inherited;
  1100. {$ENDIF}
  1101. if Z <> 1 then
  1102. begin
  1103. Z := 1 / Z;
  1104. DstX := DstX * Z;
  1105. DstY := DstY * Z;
  1106. end;
  1107. end;
  1108. { TTwirlTransformation }
  1109. constructor TTwirlTransformation.Create;
  1110. begin
  1111. FTwirl := 0.03;
  1112. end;
  1113. function TTwirlTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
  1114. var
  1115. Cx, Cy, R: TFloat;
  1116. const
  1117. CPiHalf: TFloat = 0.5 * Pi;
  1118. begin
  1119. Cx := (ASrcRect.Left + ASrcRect.Right) * 0.5;
  1120. Cy := (ASrcRect.Top + ASrcRect.Bottom) * 0.5;
  1121. R := Max(Cx - ASrcRect.Left, Cy - ASrcRect.Top);
  1122. Result.Left := Cx - R * CPiHalf;
  1123. Result.Right := Cx + R * CPiHalf;
  1124. Result.Top := Cy - R * CPiHalf;
  1125. Result.Bottom := Cy + R * CPiHalf;
  1126. end;
  1127. procedure TTwirlTransformation.PrepareTransform;
  1128. begin
  1129. with FSrcRect do
  1130. begin
  1131. Frx := (Right - Left) * 0.5;
  1132. Fry := (Bottom - Top) * 0.5;
  1133. end;
  1134. TransformValid := True;
  1135. end;
  1136. procedure TTwirlTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
  1137. out SrcX, SrcY: TFloat);
  1138. var
  1139. xf, yf, r, t: Single;
  1140. begin
  1141. xf := DstX - Frx;
  1142. yf := DstY - Fry;
  1143. r := GR32_Math.Hypot(xf, yf);
  1144. t := ArcTan2(yf, xf) + r * FTwirl;
  1145. GR32_Math.SinCos(t, yf, xf);
  1146. SrcX := Frx + r * xf;
  1147. SrcY := Fry + r * yf;
  1148. end;
  1149. procedure TTwirlTransformation.SetTwirl(const Value: TFloat);
  1150. begin
  1151. FTwirl := Value;
  1152. Changed;
  1153. end;
  1154. { TBloatTransformation }
  1155. constructor TBloatTransformation.Create;
  1156. begin
  1157. FBloatPower := 0.3;
  1158. end;
  1159. procedure TBloatTransformation.PrepareTransform;
  1160. begin
  1161. FPiW := (Pi / (FSrcRect.Right - FSrcRect.Left));
  1162. FPiH := (Pi / (FSrcRect.Bottom - FSrcRect.Top));
  1163. FBP := FBloatPower * Max(FSrcRect.Right - FSrcRect.Left, FSrcRect.Bottom - FSrcRect.Top);
  1164. TransformValid := True;
  1165. end;
  1166. procedure TBloatTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
  1167. out SrcX, SrcY: TFloat);
  1168. var
  1169. SinY, CosY, SinX, CosX, t: Single;
  1170. begin
  1171. GR32_Math.SinCos(FPiH * DstY, SinY, CosY);
  1172. GR32_Math.SinCos(FPiW * DstX, SinX, CosX);
  1173. t := FBP * SinY * SinX;
  1174. SrcX := DstX + t * CosX;
  1175. SrcY := DstY + t * CosY;
  1176. end;
  1177. procedure TBloatTransformation.TransformFloat(DstX, DstY: TFloat;
  1178. out SrcX, SrcY: TFloat);
  1179. var
  1180. SinY, CosY, SinX, CosX, t: Single;
  1181. begin
  1182. GR32_Math.SinCos(-FPiH * DstY, SinY, CosY);
  1183. GR32_Math.SinCos(-FPiW * DstX, SinX, CosX);
  1184. t := FBP * SinY * SinX;
  1185. SrcX := DstX + t * CosX;
  1186. SrcY := DstY + t * CosY;
  1187. end;
  1188. procedure TBloatTransformation.SetBloatPower(const Value: TFloat);
  1189. begin
  1190. FBloatPower := Value;
  1191. Changed;
  1192. end;
  1193. { TFishEyeTransformation }
  1194. procedure TFishEyeTransformation.PrepareTransform;
  1195. begin
  1196. with FSrcRect do
  1197. begin
  1198. Frx := (Right - Left) * 0.5;
  1199. Fry := (Bottom - Top) * 0.5;
  1200. if Frx <= Fry then
  1201. begin
  1202. FMinR := Frx;
  1203. Sx := 1;
  1204. Sy:= Frx / Fry;
  1205. end
  1206. else
  1207. begin
  1208. FMinR := Fry;
  1209. Sx:= Fry / Frx;
  1210. Sy := 1;
  1211. end;
  1212. Fsr := 1 / FMinR;
  1213. Faw := ArcSin(Constrain(FMinR * Fsr, -1, 1));
  1214. if Faw <> 0 then Faw := 1 / Faw;
  1215. Faw := Faw * FMinR
  1216. end;
  1217. TransformValid := True;
  1218. end;
  1219. procedure TFishEyeTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
  1220. out SrcX, SrcY: TFloat);
  1221. var
  1222. d, Xrx, Yry: TFloat;
  1223. begin
  1224. Yry := (DstY - Fry) * sy;
  1225. Xrx := (DstX - Frx) * sx;
  1226. d := GR32_Math.Hypot(Xrx, Yry);
  1227. if (d < FMinR) and (d > 0) then
  1228. begin
  1229. d := ArcSin(d * Fsr) * Faw / d;
  1230. SrcX := Frx + Xrx * d;
  1231. SrcY := Fry + Yry * d;
  1232. end
  1233. else
  1234. begin
  1235. SrcX := DstX;
  1236. SrcY := DstY;
  1237. end;
  1238. end;
  1239. { TPolarTransformation }
  1240. procedure TPolarTransformation.PrepareTransform;
  1241. begin
  1242. Sx := SrcRect.Right - SrcRect.Left;
  1243. Sy := SrcRect.Bottom - SrcRect.Top;
  1244. Cx := (DstRect.Left + DstRect.Right) * 0.5;
  1245. Cy := (DstRect.Top + DstRect.Bottom) * 0.5;
  1246. Dx := DstRect.Right - Cx;
  1247. Dy := DstRect.Bottom - Cy;
  1248. Rt := (1 / (PI * 2)) * Sx;
  1249. Rt2 := Sx;
  1250. if Rt2 <> 0 then Rt2 := 1 / Sx else Rt2 := 0.00000001;
  1251. Rt2 := Rt2 * 2 * Pi;
  1252. Rr := Sy;
  1253. if Rr <> 0 then Rr := 1 / Rr else Rr := 0.00000001;
  1254. Rcx := Cx;
  1255. if Rcx <> 0 then Rcx := 1 / Rcx else Rcx := 0.00000001;
  1256. Rcy := Cy;
  1257. if Rcy <> 0 then Rcy := 1 / Rcy else Rcy := 0.00000001;
  1258. TransformValid := True;
  1259. end;
  1260. procedure TPolarTransformation.SetDstRect(const Value: TFloatRect);
  1261. begin
  1262. FDstRect := Value;
  1263. Changed;
  1264. end;
  1265. procedure TPolarTransformation.TransformFloat(SrcX, SrcY: TFloat; out DstX,
  1266. DstY: TFloat);
  1267. var
  1268. R, Theta, S, C: TFloat;
  1269. begin
  1270. Theta := (SrcX - SrcRect.Left) * Rt2 + Phase;
  1271. R := (SrcY - SrcRect.Bottom) * Rr;
  1272. GR32_Math.SinCos(Theta, S, C);
  1273. DstX := Dx * R * C + Cx;
  1274. DstY := Dy * R * S + Cy;
  1275. end;
  1276. procedure TPolarTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
  1277. out SrcX, SrcY: TFloat);
  1278. const
  1279. PI2 = 2 * PI;
  1280. var
  1281. Dcx, Dcy, Theta: TFloat;
  1282. begin
  1283. Dcx := (DstX - Cx) * Rcx;
  1284. Dcy := (DstY - Cy) * Rcy;
  1285. Theta := ArcTan2(Dcy, Dcx) + Pi - Phase;
  1286. if Theta < 0 then Theta := Theta + PI2;
  1287. SrcX := SrcRect.Left + Theta * Rt;
  1288. SrcY := SrcRect.Bottom - GR32_Math.Hypot(Dcx, Dcy) * Sy;
  1289. end;
  1290. procedure TPolarTransformation.SetPhase(const Value: TFloat);
  1291. begin
  1292. FPhase := Value;
  1293. Changed;
  1294. end;
  1295. { TPathTransformation }
  1296. destructor TPathTransformation.Destroy;
  1297. begin
  1298. FTopHypot := nil;
  1299. FBottomHypot := nil;
  1300. inherited;
  1301. end;
  1302. procedure TPathTransformation.PrepareTransform;
  1303. var
  1304. I: Integer;
  1305. L, DDist: TFloat;
  1306. begin
  1307. if not (Assigned(FTopCurve) and Assigned(FBottomCurve)) then
  1308. raise ETransformError.Create(RCStrTopBottomCurveNil);
  1309. SetLength(FTopHypot, Length(FTopCurve));
  1310. SetLength(FBottomHypot, Length(FBottomCurve));
  1311. L := 0;
  1312. for I := 0 to High(FTopCurve) - 1 do
  1313. begin
  1314. FTopHypot[I].Dist := L;
  1315. with FTopCurve[I + 1] do
  1316. L := L + GR32_Math.Hypot(FTopCurve[I].X - X, FTopCurve[I].Y - Y);
  1317. end;
  1318. FTopLength := L;
  1319. for I := 1 to High(FTopCurve) do
  1320. with FTopHypot[I] do
  1321. begin
  1322. DDist := Dist - FTopHypot[I - 1].Dist;
  1323. if DDist <> 0 then
  1324. RecDist := 1 / DDist
  1325. else if I > 1 then
  1326. RecDist := FTopHypot[I - 1].RecDist
  1327. else
  1328. RecDist := 0;
  1329. end;
  1330. L := 0;
  1331. for I := 0 to High(FBottomCurve) - 1 do
  1332. begin
  1333. FBottomHypot[I].Dist := L;
  1334. with FBottomCurve[I + 1] do
  1335. L := L + GR32_Math.Hypot(FBottomCurve[I].X - X, FBottomCurve[I].Y - Y);
  1336. end;
  1337. FBottomLength := L;
  1338. for I := 1 to High(FBottomCurve) do
  1339. with FBottomHypot[I] do
  1340. begin
  1341. DDist := Dist - FBottomHypot[I - 1].Dist;
  1342. if DDist <> 0 then
  1343. RecDist := 1 / DDist
  1344. else if I > 1 then
  1345. RecDist := FBottomHypot[I - 1].RecDist
  1346. else
  1347. RecDist := 0;
  1348. end;
  1349. rdx := 1 / (SrcRect.Right - SrcRect.Left);
  1350. rdy := 1 / (SrcRect.Bottom - SrcRect.Top);
  1351. TransformValid := True;
  1352. end;
  1353. procedure TPathTransformation.SetBottomCurve(const Value: TArrayOfFloatPoint);
  1354. begin
  1355. FBottomCurve := Value;
  1356. Changed;
  1357. end;
  1358. procedure TPathTransformation.SetTopCurve(const Value: TArrayOfFloatPoint);
  1359. begin
  1360. FTopCurve := Value;
  1361. Changed;
  1362. end;
  1363. procedure TPathTransformation.TransformFloat(SrcX, SrcY: TFloat; out DstX,
  1364. DstY: TFloat);
  1365. var
  1366. I, H: Integer;
  1367. X, Y, fx, dx, dy, r, Tx, Ty, Bx, By: TFloat;
  1368. begin
  1369. X := (SrcX - SrcRect.Left) * rdx;
  1370. Y := (SrcY - SrcRect.Top) * rdy;
  1371. fx := X * FTopLength;
  1372. I := 1;
  1373. H := High(FTopHypot);
  1374. while (FTopHypot[I].Dist < fx) and (I < H) do Inc(I);
  1375. with FTopHypot[I] do
  1376. r := (Dist - fx) * RecDist;
  1377. dx := (FTopCurve[I - 1].X - FTopCurve[I].X);
  1378. dy := (FTopCurve[I - 1].Y - FTopCurve[I].Y);
  1379. Tx := FTopCurve[I].X + r * dx;
  1380. Ty := FTopCurve[I].Y + r * dy;
  1381. fx := X * FBottomLength;
  1382. I := 1;
  1383. H := High(FBottomHypot);
  1384. while (FBottomHypot[I].Dist < fx) and (I < H) do Inc(I);
  1385. with FBottomHypot[I] do
  1386. r := (Dist - fx) * RecDist;
  1387. dx := (FBottomCurve[I - 1].X - FBottomCurve[I].X);
  1388. dy := (FBottomCurve[I - 1].Y - FBottomCurve[I].Y);
  1389. Bx := FBottomCurve[I].X + r * dx;
  1390. By := FBottomCurve[I].Y + r * dy;
  1391. DstX := Tx + Y * (Bx - Tx);
  1392. DstY := Ty + Y * (By - Ty);
  1393. end;
  1394. { TDisturbanceTransformation }
  1395. function TDisturbanceTransformation.GetTransformedBounds(
  1396. const ASrcRect: TFloatRect): TFloatRect;
  1397. begin
  1398. Result := ASrcRect;
  1399. InflateRect(Result, 0.5 * FDisturbance, 0.5 * FDisturbance);
  1400. end;
  1401. procedure TDisturbanceTransformation.ReverseTransformFloat(DstX,
  1402. DstY: TFloat; out SrcX, SrcY: TFloat);
  1403. begin
  1404. SrcX := DstX + (Random - 0.5) * FDisturbance;
  1405. SrcY := DstY + (Random - 0.5) * FDisturbance;
  1406. end;
  1407. procedure TDisturbanceTransformation.SetDisturbance(const Value: TFloat);
  1408. begin
  1409. FDisturbance := Value;
  1410. Changed;
  1411. end;
  1412. { TRemapTransformation }
  1413. constructor TRemapTransformation.Create;
  1414. begin
  1415. inherited;
  1416. FScalingFixed := FixedPoint(1, 1);
  1417. FScalingFloat := FloatPoint(1, 1);
  1418. FOffset := FloatPoint(0,0);
  1419. FVectorMap := TVectorMap.Create;
  1420. //Ensuring initial setup to avoid exceptions
  1421. FVectorMap.SetSize(1, 1);
  1422. end;
  1423. destructor TRemapTransformation.Destroy;
  1424. begin
  1425. FVectorMap.Free;
  1426. inherited;
  1427. end;
  1428. function TRemapTransformation.GetTransformedBounds(const ASrcRect: TFloatRect): TFloatRect;
  1429. const
  1430. InfRect: TFloatRect = (Left: -Infinity; Top: -Infinity; Right: Infinity; Bottom: Infinity);
  1431. begin
  1432. // We can't predict the ultimate bounds without transforming each vector in
  1433. // the vector map, return the absolute biggest possible transformation bounds
  1434. Result := InfRect;
  1435. end;
  1436. function TRemapTransformation.HasTransformedBounds: Boolean;
  1437. begin
  1438. Result := False;
  1439. end;
  1440. procedure TRemapTransformation.PrepareTransform;
  1441. begin
  1442. if IsRectEmpty(SrcRect) then raise Exception.Create(RCStrSrcRectIsEmpty);
  1443. if IsRectEmpty(FMappingRect) then raise Exception.Create(RCStrMappingRectIsEmpty);
  1444. with SrcRect do
  1445. begin
  1446. FSrcTranslationFloat.X := Left;
  1447. FSrcTranslationFloat.Y := Top;
  1448. FSrcScaleFloat.X := (Right - Left) / (FVectorMap.Width - 1);
  1449. FSrcScaleFloat.Y := (Bottom - Top) / (FVectorMap.Height - 1);
  1450. FSrcTranslationFixed := FixedPoint(FSrcTranslationFloat);
  1451. FSrcScaleFixed := FixedPoint(FSrcScaleFloat);
  1452. end;
  1453. with FMappingRect do
  1454. begin
  1455. FDstTranslationFloat.X := Left;
  1456. FDstTranslationFloat.Y := Top;
  1457. FDstScaleFloat.X := (FVectorMap.Width - 1) / (Right - Left);
  1458. FDstScaleFloat.Y := (FVectorMap.Height - 1) / (Bottom - Top);
  1459. FCombinedScalingFloat.X := FDstScaleFloat.X * FScalingFloat.X;
  1460. FCombinedScalingFloat.Y := FDstScaleFloat.Y * FScalingFloat.Y;
  1461. FCombinedScalingFixed := FixedPoint(FCombinedScalingFloat);
  1462. FDstTranslationFixed := FixedPoint(FDstTranslationFloat);
  1463. FDstScaleFixed := FixedPoint(FDstScaleFloat);
  1464. end;
  1465. TransformValid := True;
  1466. end;
  1467. procedure TRemapTransformation.ReverseTransformFixed(DstX, DstY: TFixed;
  1468. out SrcX, SrcY: TFixed);
  1469. begin
  1470. with FVectorMap.FixedVectorX[DstX - FOffsetFixed.X, DstY - FOffsetFixed.Y] do
  1471. begin
  1472. DstX := DstX - FDstTranslationFixed.X;
  1473. DstX := FixedMul(DstX , FDstScaleFixed.X);
  1474. DstX := DstX + FixedMul(X, FCombinedScalingFixed.X);
  1475. DstX := FixedMul(DstX, FSrcScaleFixed.X);
  1476. SrcX := DstX + FSrcTranslationFixed.X;
  1477. DstY := DstY - FDstTranslationFixed.Y;
  1478. DstY := FixedMul(DstY, FDstScaleFixed.Y);
  1479. DstY := DstY + FixedMul(Y, FCombinedScalingFixed.Y);
  1480. DstY := FixedMul(DstY, FSrcScaleFixed.Y);
  1481. SrcY := DstY + FSrcTranslationFixed.Y;
  1482. end;
  1483. end;
  1484. procedure TRemapTransformation.ReverseTransformFloat(DstX, DstY: TFloat;
  1485. out SrcX, SrcY: TFloat);
  1486. begin
  1487. with FVectorMap.FloatVectorF[DstX - FOffset.X, DstY - FOffset.Y] do
  1488. begin
  1489. DstX := DstX - FDstTranslationFloat.X;
  1490. DstY := DstY - FDstTranslationFloat.Y;
  1491. DstX := DstX * FDstScaleFloat.X;
  1492. DstY := DstY * FDstScaleFloat.Y;
  1493. DstX := DstX + X * FCombinedScalingFloat.X;
  1494. DstY := DstY + Y * FCombinedScalingFloat.Y;
  1495. DstX := DstX * FSrcScaleFloat.X;
  1496. DstY := DstY * FSrcScaleFloat.Y;
  1497. SrcX := DstX + FSrcTranslationFloat.X;
  1498. SrcY := DstY + FSrcTranslationFloat.Y;
  1499. end;
  1500. end;
  1501. procedure TRemapTransformation.ReverseTransformInt(DstX, DstY: Integer;
  1502. out SrcX, SrcY: Integer);
  1503. begin
  1504. with FVectorMap.FixedVector[DstX - FOffsetInt.X, DstY - FOffsetInt.Y] do
  1505. begin
  1506. DstX := DstX * FixedOne - FDstTranslationFixed.X;
  1507. DstY := DstY * FixedOne - FDstTranslationFixed.Y;
  1508. DstX := FixedMul(DstX, FDstScaleFixed.X);
  1509. DstY := FixedMul(DstY, FDstScaleFixed.Y);
  1510. DstX := DstX + FixedMul(X, FCombinedScalingFixed.X);
  1511. DstY := DstY + FixedMul(Y, FCombinedScalingFixed.Y);
  1512. DstX := FixedMul(DstX, FSrcScaleFixed.X);
  1513. DstY := FixedMul(DstY, FSrcScaleFixed.Y);
  1514. SrcX := FixedRound(DstX + FSrcTranslationFixed.X);
  1515. SrcY := FixedRound(DstY + FSrcTranslationFixed.Y);
  1516. end;
  1517. end;
  1518. procedure TRemapTransformation.Scale(Sx, Sy: TFloat);
  1519. begin
  1520. FScalingFixed.X := Fixed(Sx);
  1521. FScalingFixed.Y := Fixed(Sy);
  1522. FScalingFloat.X := Sx;
  1523. FScalingFloat.Y := Sy;
  1524. Changed;
  1525. end;
  1526. procedure TRemapTransformation.SetMappingRect(Rect: TFloatRect);
  1527. begin
  1528. FMappingRect := Rect;
  1529. Changed;
  1530. end;
  1531. procedure TRemapTransformation.SetOffset(const Value: TFloatVector);
  1532. begin
  1533. FOffset := Value;
  1534. FOffsetInt := Point(Value);
  1535. FOffsetFixed := FixedPoint(Value);
  1536. Changed;
  1537. end;
  1538. procedure RasterizeTransformation(Vectormap: TVectormap;
  1539. Transformation: TTransformation; DstRect: TRect;
  1540. CombineMode: TVectorCombineMode = vcmAdd;
  1541. CombineCallback: TVectorCombineEvent = nil);
  1542. var
  1543. I, J: Integer;
  1544. P, Q, Progression: TFixedVector;
  1545. ProgressionX, ProgressionY: TFixed;
  1546. MapPtr: PFixedPointArray;
  1547. begin
  1548. GR32.IntersectRect(DstRect, VectorMap.BoundsRect, DstRect);
  1549. if GR32.IsRectEmpty(DstRect) then Exit;
  1550. if not TTransformationAccess(Transformation).TransformValid then
  1551. TTransformationAccess(Transformation).PrepareTransform;
  1552. case CombineMode of
  1553. vcmAdd:
  1554. begin
  1555. with DstRect do
  1556. for I := Top to Bottom - 1 do
  1557. begin
  1558. MapPtr := @VectorMap.Vectors[I * VectorMap.Width];
  1559. for J := Left to Right - 1 do
  1560. begin
  1561. P := FixedPoint(Integer(J - Left), Integer(I - Top));
  1562. Q := Transformation.ReverseTransform(P);
  1563. Inc(MapPtr[J].X, Q.X - P.X);
  1564. Inc(MapPtr[J].Y, Q.Y - P.Y);
  1565. end;
  1566. end;
  1567. end;
  1568. vcmReplace:
  1569. begin
  1570. with DstRect do
  1571. for I := Top to Bottom - 1 do
  1572. begin
  1573. MapPtr := @VectorMap.Vectors[I * VectorMap.Width];
  1574. for J := Left to Right - 1 do
  1575. begin
  1576. P := FixedPoint(Integer(J - Left), Integer(I - Top));
  1577. Q := Transformation.ReverseTransform(P);
  1578. MapPtr[J].X := Q.X - P.X;
  1579. MapPtr[J].Y := Q.Y - P.Y;
  1580. end;
  1581. end;
  1582. end;
  1583. else // vcmCustom
  1584. ProgressionX := Fixed(1 / (DstRect.Right - DstRect.Left - 1));
  1585. ProgressionY := Fixed(1 / (DstRect.Bottom - DstRect.Top - 1));
  1586. Progression.Y := 0;
  1587. with DstRect do for I := Top to Bottom - 1 do
  1588. begin
  1589. Progression.X := 0;
  1590. MapPtr := @VectorMap.Vectors[I * VectorMap.Width];
  1591. for J := Left to Right - 1 do
  1592. begin
  1593. P := FixedPoint(Integer(J - Left), Integer(I - Top));
  1594. Q := Transformation.ReverseTransform(P);
  1595. Q.X := Q.X - P.X;
  1596. Q.Y := Q.Y - P.Y;
  1597. CombineCallback(Q, Progression, MapPtr[J]);
  1598. Inc(Progression.X, ProgressionX);
  1599. end;
  1600. Inc(Progression.Y, ProgressionY);
  1601. end;
  1602. end;
  1603. end;
  1604. { Matrix conversion routines }
  1605. function FixedMatrix(const FloatMatrix: TFloatMatrix): TFixedMatrix;
  1606. begin
  1607. Result[0,0] := Round(FloatMatrix[0,0] * FixedOne);
  1608. Result[0,1] := Round(FloatMatrix[0,1] * FixedOne);
  1609. Result[0,2] := Round(FloatMatrix[0,2] * FixedOne);
  1610. Result[1,0] := Round(FloatMatrix[1,0] * FixedOne);
  1611. Result[1,1] := Round(FloatMatrix[1,1] * FixedOne);
  1612. Result[1,2] := Round(FloatMatrix[1,2] * FixedOne);
  1613. Result[2,0] := Round(FloatMatrix[2,0] * FixedOne);
  1614. Result[2,1] := Round(FloatMatrix[2,1] * FixedOne);
  1615. Result[2,2] := Round(FloatMatrix[2,2] * FixedOne);
  1616. end;
  1617. function FloatMatrix(const FixedMatrix: TFixedMatrix): TFloatMatrix;
  1618. begin
  1619. Result[0,0] := FixedMatrix[0,0] * FixedToFloat;
  1620. Result[0,1] := FixedMatrix[0,1] * FixedToFloat;
  1621. Result[0,2] := FixedMatrix[0,2] * FixedToFloat;
  1622. Result[1,0] := FixedMatrix[1,0] * FixedToFloat;
  1623. Result[1,1] := FixedMatrix[1,1] * FixedToFloat;
  1624. Result[1,2] := FixedMatrix[1,2] * FixedToFloat;
  1625. Result[2,0] := FixedMatrix[2,0] * FixedToFloat;
  1626. Result[2,1] := FixedMatrix[2,1] * FixedToFloat;
  1627. Result[2,2] := FixedMatrix[2,2] * FixedToFloat;
  1628. end;
  1629. {CPU target and feature Function templates}
  1630. const
  1631. FID_DETERMINANT32 = 0;
  1632. FID_DETERMINANT64 = 1;
  1633. {Complete collection of unit templates}
  1634. var
  1635. Registry: TFunctionRegistry;
  1636. procedure RegisterBindings;
  1637. begin
  1638. Registry := NewRegistry('GR32_Transforms bindings');
  1639. Registry.RegisterBinding(FID_DETERMINANT32, @@DET32);
  1640. Registry.Add(FID_DETERMINANT32, @DET32_Pas, []);
  1641. {$IFNDEF PUREPASCAL}
  1642. Registry.Add(FID_DETERMINANT32, @DET32_ASM, []);
  1643. // Registry.Add(FID_DETERMINANT32, @DET32_SSE2, [ciSSE2]);
  1644. {$ENDIF}
  1645. Registry.RegisterBinding(FID_DETERMINANT64, @@DET64);
  1646. Registry.Add(FID_DETERMINANT64, @DET64_Pas, []);
  1647. {$IFNDEF PUREPASCAL}
  1648. Registry.Add(FID_DETERMINANT64, @DET64_ASM, []);
  1649. // Registry.Add(FID_DETERMINANT64, @DET64_SSE2, [ciSSE2]);
  1650. {$ENDIF}
  1651. Registry.RebindAll;
  1652. end;
  1653. initialization
  1654. RegisterBindings;
  1655. finalization
  1656. end.