You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

459 lines
16 KiB

  1. unit ultsImage;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,
  6. utsTextSuite,
  7. ultsTypes;
  8. type
  9. TltsImageLoadFunc = procedure(aHandle: TltsImageHandle; X, Y: Integer; var aPixel: TtsColor4f; aArgs: Pointer); stdcall;
  10. TltsImageBlendFunc = procedure(aHandle: TltsImageHandle; aSrc, aDst: TtsColor4f; out aResult: TtsColor4f; aArgs: Pointer); stdcall;
  11. function ltsImageCreate (aContext: TltsContextHandle): TltsImageHandle; stdcall;
  12. function ltsImageIsEmpty (aHandle: TltsImageHandle; out aValue: Boolean): TltsErrorCode; stdcall;
  13. function ltsImageGetWidth (aHandle: TltsImageHandle): Integer; stdcall;
  14. function ltsImageGetHeight (aHandle: TltsImageHandle): Integer; stdcall;
  15. function ltsImageGetLineSize (aHandle: TltsImageHandle): Integer; stdcall;
  16. function ltsImageGetDataSize (aHandle: TltsImageHandle): Integer; stdcall;
  17. function ltsImageGetFormat (aHandle: TltsImageHandle; out aValue: TtsFormat): TltsErrorCode; stdcall;
  18. function ltsImageGetData (aHandle: TltsImageHandle): Pointer; stdcall;
  19. function ltsImageGetScanline (aHandle: TltsImageHandle; aIndex: Integer): Pointer; stdcall;
  20. function ltsImageGetPixelAt (aHandle: TltsImageHandle; aX, aY: Integer; out aColor: TtsColor4f): TltsErrorCode; stdcall;
  21. function ltsImageAssign (aHandle, aSource: TltsImageHandle): TltsErrorCode; stdcall;
  22. function ltsImageCreateEmpty (aHandle: TltsImageHandle; aFormat: TtsFormat; aWidth, aHeight: Integer): TltsErrorCode; stdcall;
  23. function ltsImageLoadFromFunc (aHandle: TltsImageHandle; aCallback: TltsImageLoadFunc; aArgs: Pointer): TltsErrorCode; stdcall;
  24. function ltsImageResize (aHandle: TltsImageHandle; aWidth, aHeight, aX, aY: Integer): TltsErrorCode; stdcall;
  25. function ltsImageFillColor (aHandle: TltsImageHandle; aColor: TtsColor4f; aMask: TtsColorChannels; aModes: TtsImageModes): TltsErrorCode; stdcall;
  26. function ltsImageFillPattern (aHandle, aPattern: TltsImageHandle; aX, aY: Integer; aMask: TtsColorChannels; aModes: TtsImageModes): TltsErrorCode; stdcall;
  27. function ltsImageBlend (aHandle, aSource: TltsImageHandle; aX, aY: Integer; aBlendFunc: TltsImageBlendFunc; aArgs: Pointer): TltsErrorCode; stdcall;
  28. function ltsImageBlur (aHandle: TltsImageHandle; aHorzRad, aHorzStr, aVertRad, aVertStr: Single; aMask: TtsColorChannels): TltsErrorCode; stdcall;
  29. function ltsImageDestroy (aHandle: TltsImageHandle): TltsErrorCode; stdcall;
  30. implementation
  31. uses
  32. ultsUtils, utsUtils;
  33. type
  34. PLoadArgs = ^TLoadArgs;
  35. TLoadArgs = packed record
  36. args: Pointer;
  37. handle: TltsImageHandle;
  38. callback: TltsImageLoadFunc
  39. end;
  40. PBlendArgs = ^TBlendArgs;
  41. TBlendArgs = packed record
  42. args: Pointer;
  43. handle: TltsImageHandle;
  44. callback: TltsImageBlendFunc;
  45. end;
  46. procedure ImageLoadCallback(const aImage: TtsImage; X, Y: Integer; var aPixel: TtsColor4f; aArgs: Pointer);
  47. var
  48. p: PLoadArgs;
  49. begin
  50. p := PLoadArgs(aArgs);
  51. p^.callback(p^.handle, X, Y, aPixel, p^.args);
  52. end;
  53. function ImageBlendCallback(const aSrc, aDst: TtsColor4f; aArgs: Pointer): TtsColor4f;
  54. var
  55. p: PBlendArgs;
  56. begin
  57. p := PBlendArgs(aArgs);
  58. p^.callback(p^.handle, aSrc, aDst, result, p^.args);
  59. end;
  60. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  61. //ltsImage//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  62. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  63. function ltsImageCreate(aContext: TltsContextHandle): TltsImageHandle; stdcall;
  64. var
  65. img: TtsImage;
  66. c: TtsContext;
  67. begin
  68. try
  69. result := nil;
  70. if not CheckContextHandle(aContext, c) then
  71. exit;
  72. img := TtsImage.Create(c);
  73. AddReference(ltsObjTypeImage, img);
  74. result := img;
  75. except
  76. on ex: Exception do begin
  77. SetLastError(ex);
  78. result := nil;
  79. end;
  80. end;
  81. end;
  82. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  83. function ltsImageIsEmpty(aHandle: TltsImageHandle; out aValue: Boolean): TltsErrorCode; stdcall;
  84. var
  85. img: TtsImage;
  86. begin
  87. try
  88. result := ltsErrNone;
  89. if CheckImageHandle(aHandle, img)
  90. then aValue := img.IsEmpty
  91. else result := LastErrorCode;
  92. except
  93. on ex: Exception do begin
  94. SetLastError(ex);
  95. result := LastErrorCode;
  96. end;
  97. end;
  98. end;
  99. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  100. function ltsImageGetWidth(aHandle: TltsImageHandle): Integer; stdcall;
  101. var
  102. img: TtsImage;
  103. begin
  104. try
  105. if CheckImageHandle(aHandle, img)
  106. then result := img.Width
  107. else result := -1;
  108. except
  109. on ex: Exception do begin
  110. SetLastError(ex);
  111. result := -1;
  112. end;
  113. end;
  114. end;
  115. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  116. function ltsImageGetHeight(aHandle: TltsImageHandle): Integer; stdcall;
  117. var
  118. img: TtsImage;
  119. begin
  120. try
  121. if CheckImageHandle(aHandle, img)
  122. then result := img.Height
  123. else result := -1;
  124. except
  125. on ex: Exception do begin
  126. SetLastError(ex);
  127. result := -1;
  128. end;
  129. end;
  130. end;
  131. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  132. function ltsImageGetLineSize(aHandle: TltsImageHandle): Integer; stdcall;
  133. var
  134. img: TtsImage;
  135. begin
  136. try
  137. if CheckImageHandle(aHandle, img)
  138. then result := img.LineSize
  139. else result := -1;
  140. except
  141. on ex: Exception do begin
  142. SetLastError(ex);
  143. result := -1;
  144. end;
  145. end;
  146. end;
  147. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  148. function ltsImageGetDataSize(aHandle: TltsImageHandle): Integer; stdcall;
  149. var
  150. img: TtsImage;
  151. begin
  152. try
  153. if CheckImageHandle(aHandle, img)
  154. then result := img.DataSize
  155. else result := -1;
  156. except
  157. on ex: Exception do begin
  158. SetLastError(ex);
  159. result := -1;
  160. end;
  161. end;
  162. end;
  163. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  164. function ltsImageGetFormat(aHandle: TltsImageHandle; out aValue: TtsFormat): TltsErrorCode; stdcall;
  165. var
  166. img: TtsImage;
  167. begin
  168. try
  169. result := ltsErrNone;
  170. if CheckImageHandle(aHandle, img)
  171. then aValue := img.Format
  172. else result := LastErrorCode;
  173. except
  174. on ex: Exception do begin
  175. SetLastError(ex);
  176. result := LastErrorCode;
  177. end;
  178. end;
  179. end;
  180. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  181. function ltsImageGetData(aHandle: TltsImageHandle): Pointer; stdcall;
  182. var
  183. img: TtsImage;
  184. begin
  185. try
  186. if CheckImageHandle(aHandle, img)
  187. then result := img.Data
  188. else result := nil;
  189. except
  190. on ex: Exception do begin
  191. SetLastError(ex);
  192. result := nil;
  193. end;
  194. end;
  195. end;
  196. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  197. function ltsImageGetScanline(aHandle: TltsImageHandle; aIndex: Integer): Pointer; stdcall;
  198. var
  199. img: TtsImage;
  200. begin
  201. try
  202. if CheckImageHandle(aHandle, img) then begin
  203. result := img.Scanline[aIndex];
  204. if not Assigned(result) then
  205. SetLastError(ltsErrInvalidValue, Format('index (%d) is out of range', [aIndex]));
  206. end else
  207. result := nil;
  208. except
  209. on ex: Exception do begin
  210. SetLastError(ex);
  211. result := nil;
  212. end;
  213. end;
  214. end;
  215. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  216. function ltsImageGetPixelAt(aHandle: TltsImageHandle; aX, aY: Integer; out aColor: TtsColor4f): TltsErrorCode; stdcall;
  217. var
  218. img: TtsImage;
  219. begin
  220. try
  221. result := ltsErrNone;
  222. if CheckImageHandle(aHandle, img) then begin
  223. if not img.GetPixelAt(aX, aY, aColor) then begin
  224. SetLastError(ltsErrInvalidValue, Format('x (%d) or y (%d) is out of range', [aX, aY]));
  225. result := LastErrorCode;
  226. end;
  227. end else
  228. result := LastErrorCode;
  229. except
  230. on ex: Exception do begin
  231. SetLastError(ex);
  232. result := LastErrorCode;
  233. end;
  234. end;
  235. end;
  236. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  237. function ltsImageAssign(aHandle, aSource: TltsImageHandle): TltsErrorCode; stdcall;
  238. var
  239. img, src: TtsImage;
  240. begin
  241. try
  242. result := ltsErrNone;
  243. if CheckImageHandle(aHandle, img) and CheckImageHandle(aSource, src)
  244. then img.Assign(src)
  245. else result := LastErrorCode;
  246. except
  247. on ex: Exception do begin
  248. SetLastError(ex);
  249. result := LastErrorCode;
  250. end;
  251. end;
  252. end;
  253. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  254. function ltsImageCreateEmpty(aHandle: TltsImageHandle; aFormat: TtsFormat; aWidth, aHeight: Integer): TltsErrorCode; stdcall;
  255. var
  256. img: TtsImage;
  257. begin
  258. try
  259. result := ltsErrNone;
  260. if not ValidateFormat(aFormat) then begin
  261. result := LastErrorCode;
  262. end else if (aWidth < 0) then begin
  263. SetLastError(ltsErrInvalidValue, 'width must be a positive value');
  264. result := LastErrorCode;
  265. end else if (aHeight < 0) then begin
  266. SetLastError(ltsErrInvalidValue, 'height must be a positive value');
  267. result := LastErrorCode;
  268. end else if not CheckImageHandle(aHandle, img) then begin
  269. result := LastErrorCode;
  270. end else
  271. img.CreateEmpty(aFormat, aWidth, aHeight);
  272. except
  273. on ex: Exception do begin
  274. SetLastError(ex);
  275. result := LastErrorCode;
  276. end;
  277. end;
  278. end;
  279. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  280. function ltsImageLoadFromFunc(aHandle: TltsImageHandle; aCallback: TltsImageLoadFunc; aArgs: Pointer): TltsErrorCode; stdcall;
  281. var
  282. img: TtsImage;
  283. la: TLoadArgs;
  284. begin
  285. try
  286. result := ltsErrNone;
  287. if CheckImageHandle(aHandle, img) then begin
  288. la.args := aArgs;
  289. la.callback := aCallback;
  290. la.handle := aHandle;
  291. img.LoadFromFunc(@ImageLoadCallback, @la);
  292. end else
  293. result := LastErrorCode;
  294. except
  295. on ex: Exception do begin
  296. SetLastError(ex);
  297. result := LastErrorCode;
  298. end;
  299. end;
  300. end;
  301. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  302. function ltsImageResize(aHandle: TltsImageHandle; aWidth, aHeight, aX, aY: Integer): TltsErrorCode; stdcall;
  303. var
  304. img: TtsImage;
  305. begin
  306. try
  307. result := ltsErrNone;
  308. if (aWidth < 0) then begin
  309. SetLastError(ltsErrInvalidValue, 'width must be a positive value');
  310. result := LastErrorCode;
  311. end else if (aHeight < 0) then begin
  312. SetLastError(ltsErrInvalidValue, 'height must be a positive value');
  313. result := LastErrorCode;
  314. end else if not CheckImageHandle(aHandle, img) then begin
  315. result := LastErrorCode;
  316. end else
  317. img.Resize(aWidth, aHeight, aX, aY);
  318. except
  319. on ex: Exception do begin
  320. SetLastError(ex);
  321. result := LastErrorCode;
  322. end;
  323. end;
  324. end;
  325. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  326. function ltsImageFillColor(aHandle: TltsImageHandle; aColor: TtsColor4f; aMask: TtsColorChannels; aModes: TtsImageModes): TltsErrorCode; stdcall;
  327. var
  328. img: TtsImage;
  329. begin
  330. try
  331. result := ltsErrNone;
  332. if CheckImageHandle(aHandle, img)
  333. then img.FillColor(aColor, aMask, aModes)
  334. else result := LastErrorCode;
  335. except
  336. on ex: Exception do begin
  337. SetLastError(ex);
  338. result := LastErrorCode;
  339. end;
  340. end;
  341. end;
  342. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  343. function ltsImageFillPattern(aHandle, aPattern: TltsImageHandle; aX, aY: Integer; aMask: TtsColorChannels; aModes: TtsImageModes): TltsErrorCode; stdcall;
  344. var
  345. img, pattern: TtsImage;
  346. begin
  347. try
  348. result := ltsErrNone;
  349. if CheckImageHandle(aHandle, img) and CheckImageHandle(aPattern, pattern)
  350. then img.FillPattern(pattern, aX, aY, aMask, aModes)
  351. else result := LastErrorCode;
  352. except
  353. on ex: Exception do begin
  354. SetLastError(ex);
  355. result := LastErrorCode;
  356. end;
  357. end;
  358. end;
  359. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  360. function ltsImageBlend(aHandle, aSource: TltsImageHandle; aX, aY: Integer; aBlendFunc: TltsImageBlendFunc; aArgs: Pointer): TltsErrorCode; stdcall;
  361. var
  362. img, src: TtsImage;
  363. ba: TBlendArgs;
  364. begin
  365. try
  366. result := ltsErrNone;
  367. if CheckImageHandle(aHandle, img) and CheckImageHandle(aSource, src) then begin
  368. ba.args := aArgs;
  369. ba.handle := aHandle;
  370. ba.callback := aBlendFunc;
  371. img.Blend(src, aX, aY, @ImageBlendCallback, @ba);
  372. end else
  373. result := LastErrorCode;
  374. except
  375. on ex: Exception do begin
  376. SetLastError(ex);
  377. result := LastErrorCode;
  378. end;
  379. end;
  380. end;
  381. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  382. function ltsImageBlur(aHandle: TltsImageHandle; aHorzRad, aHorzStr, aVertRad, aVertStr: Single; aMask: TtsColorChannels): TltsErrorCode; stdcall;
  383. var
  384. img: TtsImage;
  385. horz, vert: TtsKernel1D;
  386. begin
  387. try
  388. result := ltsErrNone;
  389. if CheckImageHandle(aHandle, img) then begin
  390. horz := TtsKernel1D.Create(aHorzRad, aHorzStr);
  391. vert := TtsKernel1D.Create(aVertRad, aVertStr);
  392. try
  393. img.Blur(horz, vert, aMask);
  394. finally
  395. FreeAndNil(horz);
  396. FreeAndNil(vert);
  397. end;
  398. end else
  399. result := LastErrorCode;
  400. except
  401. on ex: Exception do begin
  402. SetLastError(ex);
  403. result := LastErrorCode;
  404. end;
  405. end;
  406. end;
  407. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  408. function ltsImageDestroy(aHandle: TltsImageHandle): TltsErrorCode; stdcall;
  409. var
  410. img: TtsImage;
  411. begin
  412. try
  413. result := ltsErrNone;
  414. if CheckImageHandle(aHandle, img) then begin
  415. DelReference(ltsObjTypeImage, img);
  416. FreeAndNil(img);
  417. end else
  418. result := LastErrorCode;
  419. except
  420. on ex: Exception do begin
  421. SetLastError(ex);
  422. result := LastErrorCode;
  423. end;
  424. end;
  425. end;
  426. end.