2
0

GR32_OrdinalMaps.pas 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372
  1. unit GR32_OrdinalMaps;
  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. * Mattias Andersson
  26. * (parts of this unit were merged from GR32_ByteMaps.pas by Alex A. Denisov)
  27. *
  28. * Portions created by the Initial Developer are Copyright (C) 2000-2009
  29. * the Initial Developer. All Rights Reserved.
  30. *
  31. * ***** END LICENSE BLOCK ***** *)
  32. interface
  33. {$include GR32.inc}
  34. uses
  35. Classes,
  36. GR32;
  37. type
  38. TConversionType = (ctRed, ctGreen, ctBlue, ctAlpha, ctUniformRGB, ctWeightedRGB);
  39. {$IFDEF FPC}
  40. PInteger = ^Integer;
  41. {$ENDIF}
  42. TBooleanMap = class(TCustomMap)
  43. private
  44. function GetValue(X, Y: Integer): Boolean;
  45. procedure SetValue(X, Y: Integer; const Value: Boolean);
  46. protected
  47. FBits: PByteArray;
  48. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
  49. public
  50. constructor Create; overload; override;
  51. destructor Destroy; override;
  52. function Empty: Boolean; override;
  53. procedure Clear(FillValue: Boolean = False); overload;
  54. procedure Clear(FillValue: Byte); overload;
  55. procedure ToggleBit(X, Y: Integer);
  56. property Value[X, Y: Integer]: Boolean read GetValue write SetValue; default;
  57. property Bits: PByteArray read FBits;
  58. end;
  59. TByteMap = class(TCustomMap)
  60. private
  61. function GetValue(X, Y: Integer): Byte; {$IFDEF USEINLINING} inline; {$ENDIF}
  62. function GetValPtr(X, Y: Integer): PByte; {$IFDEF USEINLINING} inline; {$ENDIF}
  63. procedure SetValue(X, Y: Integer; Value: Byte); {$IFDEF USEINLINING} inline; {$ENDIF}
  64. function GetScanline(Y: Integer): PByteArray;
  65. protected
  66. FBits: PByteArray;
  67. procedure AssignTo(Dst: TPersistent); override;
  68. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
  69. public
  70. constructor Create; overload; override;
  71. destructor Destroy; override;
  72. procedure Assign(Source: TPersistent); override;
  73. function Empty: Boolean; override;
  74. procedure Clear(FillValue: Byte);
  75. procedure Multiply(Value: Byte);
  76. procedure Add(Value: Byte);
  77. procedure Sub(Value: Byte);
  78. procedure ReadFrom(Source: TCustomBitmap32; Conversion: TConversionType);
  79. procedure WriteTo(Dest: TCustomBitmap32; Conversion: TConversionType); overload;
  80. procedure WriteTo(Dest: TCustomBitmap32; const Palette: TPalette32); overload;
  81. procedure DrawTo(Dest: TCustomBitmap32; X, Y: Integer; Color: TColor32); overload;
  82. procedure DrawTo(Dest: TCustomBitmap32; Rect: TRect; Color: TColor32); overload;
  83. procedure Downsample(Factor: Byte); overload;
  84. procedure Downsample(Dest: TByteMap; Factor: Byte); overload;
  85. procedure FlipHorz(Dst: TByteMap = nil);
  86. procedure FlipVert(Dst: TByteMap = nil);
  87. procedure Rotate90(Dst: TByteMap = nil);
  88. procedure Rotate180(Dst: TByteMap = nil);
  89. procedure Rotate270(Dst: TByteMap = nil);
  90. property Bits: PByteArray read FBits;
  91. property Scanline[Y: Integer]: PByteArray read GetScanline;
  92. property ValPtr[X, Y: Integer]: PByte read GetValPtr;
  93. property Value[X, Y: Integer]: Byte read GetValue write SetValue; default;
  94. end;
  95. { TWordMap }
  96. TWordMap = class(TCustomMap)
  97. private
  98. function GetValPtr(X, Y: Integer): PWord; {$IFDEF USEINLINING} inline; {$ENDIF}
  99. function GetValue(X, Y: Integer): Word; {$IFDEF USEINLINING} inline; {$ENDIF}
  100. procedure SetValue(X, Y: Integer; const Value: Word); {$IFDEF USEINLINING} inline; {$ENDIF}
  101. function GetScanline(Y: Integer): PWordArray;
  102. protected
  103. FBits: PWordArray;
  104. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
  105. public
  106. constructor Create; overload; override;
  107. destructor Destroy; override;
  108. procedure Assign(Source: TPersistent); override;
  109. function Empty: Boolean; override;
  110. procedure Clear(FillValue: Word);
  111. property ValPtr[X, Y: Integer]: PWord read GetValPtr;
  112. property Value[X, Y: Integer]: Word read GetValue write SetValue; default;
  113. property Bits: PWordArray read FBits;
  114. property Scanline[Y: Integer]: PWordArray read GetScanline;
  115. end;
  116. { TIntegerMap }
  117. TIntegerMap = class(TCustomMap)
  118. private
  119. function GetValPtr(X, Y: Integer): PInteger; {$IFDEF USEINLINING} inline; {$ENDIF}
  120. function GetValue(X, Y: Integer): Integer; {$IFDEF USEINLINING} inline; {$ENDIF}
  121. procedure SetValue(X, Y: Integer; const Value: Integer); {$IFDEF USEINLINING} inline; {$ENDIF}
  122. function GetScanline(Y: Integer): PIntegerArray;
  123. protected
  124. FBits: PIntegerArray;
  125. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
  126. public
  127. constructor Create; overload; override;
  128. destructor Destroy; override;
  129. procedure Assign(Source: TPersistent); override;
  130. function Empty: Boolean; override;
  131. procedure Clear(FillValue: Integer = 0);
  132. property ValPtr[X, Y: Integer]: PInteger read GetValPtr;
  133. property Value[X, Y: Integer]: Integer read GetValue write SetValue; default;
  134. property Bits: PIntegerArray read FBits;
  135. property Scanline[Y: Integer]: PIntegerArray read GetScanline;
  136. end;
  137. { TCardinalMap }
  138. TCardinalMap = class(TCustomMap)
  139. private
  140. function GetValPtr(X, Y: Cardinal): PCardinal; {$IFDEF USEINLINING} inline; {$ENDIF}
  141. function GetValue(X, Y: Cardinal): Cardinal; {$IFDEF USEINLINING} inline; {$ENDIF}
  142. procedure SetValue(X, Y: Cardinal; const Value: Cardinal); {$IFDEF USEINLINING} inline; {$ENDIF}
  143. function GetScanline(Y: Integer): PCardinalArray;
  144. protected
  145. FBits: PCardinalArray;
  146. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
  147. public
  148. constructor Create; overload; override;
  149. destructor Destroy; override;
  150. procedure Assign(Source: TPersistent); override;
  151. function Empty: Boolean; override;
  152. procedure Clear(FillValue: Cardinal = 0);
  153. property ValPtr[X, Y: Cardinal]: PCardinal read GetValPtr;
  154. property Value[X, Y: Cardinal]: Cardinal read GetValue write SetValue; default;
  155. property Bits: PCardinalArray read FBits;
  156. property Scanline[Y: Integer]: PCardinalArray read GetScanline;
  157. end;
  158. { TFloatMap }
  159. TFloatMap = class(TCustomMap)
  160. private
  161. function GetValPtr(X, Y: Integer): GR32.PFloat; {$IFDEF USEINLINING} inline; {$ENDIF}
  162. function GetValue(X, Y: Integer): TFloat; {$IFDEF USEINLINING} inline; {$ENDIF}
  163. procedure SetValue(X, Y: Integer; const Value: TFloat); {$IFDEF USEINLINING} inline; {$ENDIF}
  164. function GetScanline(Y: Integer): PFloatArray;
  165. protected
  166. FBits: PFloatArray;
  167. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
  168. public
  169. constructor Create; overload; override;
  170. destructor Destroy; override;
  171. procedure Assign(Source: TPersistent); override;
  172. function Empty: Boolean; override;
  173. procedure Clear; overload;
  174. procedure Clear(FillValue: TFloat); overload;
  175. property ValPtr[X, Y: Integer]: PFloat read GetValPtr;
  176. property Value[X, Y: Integer]: TFloat read GetValue write SetValue; default;
  177. property Bits: PFloatArray read FBits;
  178. property Scanline[Y: Integer]: PFloatArray read GetScanline;
  179. end;
  180. { TGenericMap<T> }
  181. TGenericMap<T> = class(TCustomMap)
  182. private
  183. function GetValue(X, Y: Integer): T; {$IFDEF USEINLINING} inline; {$ENDIF}
  184. procedure SetValue(X, Y: Integer; const Value: T); {$IFDEF USEINLINING} inline; {$ENDIF}
  185. protected
  186. FBits: Pointer;
  187. procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
  188. public
  189. constructor Create; overload; override;
  190. destructor Destroy; override;
  191. procedure Assign(Source: TPersistent); override;
  192. function Empty: Boolean; override;
  193. procedure Clear; overload;
  194. procedure Clear(FillValue: T); overload;
  195. property Value[X, Y: Integer]: T read GetValue write SetValue; default;
  196. property Bits: Pointer read FBits;
  197. end;
  198. implementation
  199. uses
  200. Math,
  201. GR32_LowLevel,
  202. GR32_Blend,
  203. GR32_Resamplers;
  204. function Bytes(Bits: Integer): Integer;
  205. begin
  206. Result := (Bits - 1) shr 3 + 1;
  207. end;
  208. { TBooleanMap }
  209. constructor TBooleanMap.Create;
  210. begin
  211. FreeMem(FBits);
  212. inherited Create;
  213. end;
  214. procedure TBooleanMap.ChangeSize(var Width, Height: Integer; NewWidth,
  215. NewHeight: Integer);
  216. begin
  217. ReallocMem(FBits, Bytes(NewWidth * NewHeight));
  218. Width := NewWidth;
  219. Height := NewHeight;
  220. end;
  221. procedure TBooleanMap.Clear(FillValue: Boolean);
  222. begin
  223. if (FillValue) then
  224. Clear($FF)
  225. else
  226. Clear(0);
  227. end;
  228. procedure TBooleanMap.Clear(FillValue: Byte);
  229. begin
  230. FillChar(FBits^, Bytes(Width * Height), FillValue);
  231. end;
  232. destructor TBooleanMap.Destroy;
  233. begin
  234. FreeMem(FBits);
  235. inherited;
  236. end;
  237. function TBooleanMap.Empty: Boolean;
  238. begin
  239. Result := (Width = 0) or (Height = 0) or (FBits = nil);
  240. end;
  241. function TBooleanMap.GetValue(X, Y: Integer): Boolean;
  242. begin
  243. X := X + Y * Width;
  244. Result := FBits^[X shr 3] and (1 shl (X and 7)) <> 0;
  245. end;
  246. procedure TBooleanMap.SetValue(X, Y: Integer; const Value: Boolean);
  247. begin
  248. X := X + Y * Width;
  249. if Value then
  250. FBits^[X shr 3] := FBits^[X shr 3] or (1 shl (X and 7))
  251. else
  252. FBits^[X shr 3] := FBits^[X shr 3] and ((1 shl (X and 7)) xor $FF);
  253. end;
  254. procedure TBooleanMap.ToggleBit(X, Y: Integer);
  255. begin
  256. X := X + Y * Width;
  257. FBits^[X shr 3] := FBits^[X shr 3] xor (1 shl (X and 7));
  258. end;
  259. { TByteMap }
  260. constructor TByteMap.Create;
  261. begin
  262. FBits := nil;
  263. inherited Create;
  264. end;
  265. destructor TByteMap.Destroy;
  266. begin
  267. FreeMem(FBits);
  268. inherited;
  269. end;
  270. procedure TByteMap.Downsample(Factor: Byte);
  271. begin
  272. // downsample inplace
  273. case Factor of
  274. 2:
  275. DownsampleByteMap2x(Self, Self);
  276. 3:
  277. DownsampleByteMap3x(Self, Self);
  278. 4:
  279. DownsampleByteMap4x(Self, Self);
  280. 6:
  281. begin
  282. DownsampleByteMap3x(Self, Self);
  283. DownsampleByteMap2x(Self, Self);
  284. end;
  285. 8:
  286. begin
  287. DownsampleByteMap4x(Self, Self);
  288. DownsampleByteMap2x(Self, Self);
  289. end;
  290. 9:
  291. begin
  292. DownsampleByteMap3x(Self, Self);
  293. DownsampleByteMap3x(Self, Self);
  294. end;
  295. 12:
  296. begin
  297. DownsampleByteMap4x(Self, Self);
  298. DownsampleByteMap3x(Self, Self);
  299. end;
  300. 16:
  301. begin
  302. DownsampleByteMap4x(Self, Self);
  303. DownsampleByteMap4x(Self, Self);
  304. end;
  305. 18:
  306. begin
  307. DownsampleByteMap3x(Self, Self);
  308. DownsampleByteMap3x(Self, Self);
  309. DownsampleByteMap2x(Self, Self);
  310. end;
  311. 24:
  312. begin
  313. DownsampleByteMap4x(Self, Self);
  314. DownsampleByteMap3x(Self, Self);
  315. DownsampleByteMap2x(Self, Self);
  316. end;
  317. 27:
  318. begin
  319. DownsampleByteMap3x(Self, Self);
  320. DownsampleByteMap3x(Self, Self);
  321. DownsampleByteMap3x(Self, Self);
  322. end;
  323. 32:
  324. begin
  325. DownsampleByteMap4x(Self, Self);
  326. DownsampleByteMap4x(Self, Self);
  327. DownsampleByteMap2x(Self, Self);
  328. end;
  329. end;
  330. end;
  331. procedure TByteMap.Downsample(Dest: TByteMap; Factor: Byte);
  332. procedure DownsampleAndMove;
  333. var
  334. Temp: TByteMap;
  335. Y: Integer;
  336. begin
  337. // clone destination and downsample inplace
  338. Temp := TByteMap.Create;
  339. Temp.Assign(Self);
  340. Temp.Downsample(Factor);
  341. // copy downsampled result
  342. Dest.SetSize(Width div Factor, Height div Factor);
  343. for Y := 0 to Dest.Height - 1 do
  344. Move(Temp.Scanline[Y]^, Dest.Scanline[Y]^, Dest.Width);
  345. end;
  346. begin
  347. // downsample directly
  348. if (Dest = Self) or not (Factor in [2, 3, 4]) then
  349. begin
  350. DownsampleAndMove;
  351. Exit;
  352. end;
  353. case Factor of
  354. 2:
  355. begin
  356. Dest.SetSize(Width div 2, Height div 2);
  357. DownsampleByteMap2x(Self, Dest);
  358. end;
  359. 3:
  360. begin
  361. // downsample directly
  362. Dest.SetSize(Width div 3, Height div 3);
  363. DownsampleByteMap3x(Self, Dest);
  364. end;
  365. 4:
  366. begin
  367. // downsample directly
  368. Dest.SetSize(Width div 4, Height div 4);
  369. DownsampleByteMap4x(Self, Dest);
  370. end;
  371. end;
  372. end;
  373. procedure TByteMap.Assign(Source: TPersistent);
  374. begin
  375. BeginUpdate;
  376. try
  377. if Source is TByteMap then
  378. begin
  379. inherited SetSize(TByteMap(Source).Width, TByteMap(Source).Height);
  380. Move(TByteMap(Source).Bits[0], Bits[0], Width * Height);
  381. end
  382. else if Source is TBitmap32 then
  383. ReadFrom(TBitmap32(Source), ctWeightedRGB)
  384. else
  385. inherited;
  386. finally
  387. EndUpdate;
  388. Changed;
  389. end;
  390. end;
  391. procedure TByteMap.AssignTo(Dst: TPersistent);
  392. begin
  393. if Dst is TBitmap32 then WriteTo(TBitmap32(Dst), ctUniformRGB)
  394. else inherited;
  395. end;
  396. procedure TByteMap.ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer);
  397. begin
  398. ReallocMem(FBits, NewWidth * NewHeight);
  399. Width := NewWidth;
  400. Height := NewHeight;
  401. end;
  402. procedure TByteMap.Clear(FillValue: Byte);
  403. begin
  404. FillChar(Bits^, Width * Height, FillValue);
  405. Changed;
  406. end;
  407. function TByteMap.Empty: Boolean;
  408. begin
  409. Result := (Width = 0) or (Height = 0) or (FBits = nil);
  410. end;
  411. procedure TByteMap.FlipHorz(Dst: TByteMap);
  412. var
  413. i, j: Integer;
  414. P1, P2: PByte;
  415. tmp: Byte;
  416. W, W2: Integer;
  417. begin
  418. W := Width;
  419. if (Dst = nil) or (Dst = Self) then
  420. begin
  421. { In-place flipping }
  422. P1 := PByte(Bits);
  423. P2 := P1;
  424. Inc(P2, Width - 1);
  425. W2 := Width shr 1;
  426. for J := 0 to Height - 1 do
  427. begin
  428. for I := 0 to W2 - 1 do
  429. begin
  430. tmp := P1^;
  431. P1^ := P2^;
  432. P2^ := tmp;
  433. Inc(P1);
  434. Dec(P2);
  435. end;
  436. Inc(P1, W - W2);
  437. Inc(P2, W + W2);
  438. end;
  439. Changed;
  440. end
  441. else
  442. begin
  443. { Flip to Dst }
  444. Dst.BeginUpdate;
  445. Dst.SetSize(W, Height);
  446. P1 := PByte(Bits);
  447. P2 := PByte(Dst.Bits);
  448. Inc(P2, W - 1);
  449. for J := 0 to Height - 1 do
  450. begin
  451. for I := 0 to W - 1 do
  452. begin
  453. P2^ := P1^;
  454. Inc(P1);
  455. Dec(P2);
  456. end;
  457. Inc(P2, W shl 1);
  458. end;
  459. Dst.EndUpdate;
  460. Dst.Changed;
  461. end;
  462. end;
  463. procedure TByteMap.FlipVert(Dst: TByteMap);
  464. var
  465. J, J2: Integer;
  466. Buffer: PByteArray;
  467. P1, P2: PByte;
  468. begin
  469. if (Dst = nil) or (Dst = Self) then
  470. begin
  471. { in-place }
  472. J2 := Height - 1;
  473. GetMem(Buffer, Width);
  474. for J := 0 to Height div 2 - 1 do
  475. begin
  476. P1 := PByte(ScanLine[J]);
  477. P2 := PByte(ScanLine[J2]);
  478. Move(P1^, Buffer^, Width);
  479. Move(P2^, P1^, Width);
  480. Move(Buffer^, P2^, Width);
  481. Dec(J2);
  482. end;
  483. FreeMem(Buffer);
  484. Changed;
  485. end
  486. else
  487. begin
  488. Dst.SetSize(Width, Height);
  489. J2 := Height - 1;
  490. for J := 0 to Height - 1 do
  491. begin
  492. Move(ScanLine[J]^, Dst.ScanLine[J2]^, Width);
  493. Dec(J2);
  494. end;
  495. Dst.Changed;
  496. end;
  497. end;
  498. function TByteMap.GetScanline(Y: Integer): PByteArray;
  499. begin
  500. Result := @FBits^[Y * Width];
  501. end;
  502. function TByteMap.GetValPtr(X, Y: Integer): PByte;
  503. begin
  504. Result := @FBits^[X + Y * Width];
  505. end;
  506. function TByteMap.GetValue(X, Y: Integer): Byte;
  507. begin
  508. Result := FBits^[X + Y * Width];
  509. end;
  510. procedure TByteMap.Multiply(Value: Byte);
  511. var
  512. Index: Integer;
  513. begin
  514. for Index := 0 to FWidth * FHeight - 1 do
  515. FBits^[Index] := ((FBits^[Index] * Value + $80) shr 8);
  516. end;
  517. procedure TByteMap.Add(Value: Byte);
  518. var
  519. Index: Integer;
  520. begin
  521. for Index := 0 to FWidth * FHeight - 1 do
  522. FBits^[Index] := Min(FBits^[Index] + Value, 255);
  523. end;
  524. procedure TByteMap.Sub(Value: Byte);
  525. var
  526. Index: Integer;
  527. begin
  528. for Index := 0 to FWidth * FHeight - 1 do
  529. FBits^[Index] := Max(FBits^[Index] - Value, 0);
  530. end;
  531. procedure TByteMap.ReadFrom(Source: TCustomBitmap32; Conversion: TConversionType);
  532. var
  533. W, H, I, N: Integer;
  534. SrcC: PColor32;
  535. SrcB, DstB: PByte;
  536. LValue: TColor32;
  537. begin
  538. BeginUpdate;
  539. try
  540. SetSize(Source.Width, Source.Height);
  541. if Empty then
  542. Exit;
  543. W := Source.Width;
  544. H := Source.Height;
  545. N := W * H - 1;
  546. DstB := @FBits^;
  547. case Conversion of
  548. ctRed,
  549. ctGreen,
  550. ctBlue,
  551. ctAlpha:
  552. begin
  553. case Conversion of
  554. ctRed:
  555. SrcB := @(PColor32Entry(Source.Bits).R);
  556. ctGreen:
  557. SrcB := @(PColor32Entry(Source.Bits).G);
  558. ctBlue:
  559. SrcB := @(PColor32Entry(Source.Bits).B);
  560. ctAlpha:
  561. SrcB := @(PColor32Entry(Source.Bits).A);
  562. else
  563. SrcB := nil;
  564. end;
  565. for I := 0 to N do
  566. begin
  567. DstB^ := SrcB^;
  568. Inc(DstB);
  569. Inc(SrcB, SizeOf(TColor32));
  570. end;
  571. end;
  572. ctUniformRGB:
  573. begin
  574. SrcC := PColor32(Source.Bits);
  575. for I := 0 to N do
  576. begin
  577. LValue := SrcC^;
  578. LValue := (LValue and $00FF0000) shr 16 + (LValue and $0000FF00) shr 8 + (LValue and $000000FF);
  579. LValue := LValue div 3;
  580. DstB^ := LValue;
  581. Inc(DstB);
  582. Inc(SrcC);
  583. end;
  584. end;
  585. ctWeightedRGB:
  586. begin
  587. SrcC := PColor32(Source.Bits);
  588. for I := 0 to N do
  589. begin
  590. DstB^ := Intensity(SrcC^);
  591. Inc(DstB);
  592. Inc(SrcC);
  593. end;
  594. end;
  595. end;
  596. Changed;
  597. finally
  598. EndUpdate;
  599. end;
  600. end;
  601. procedure TByteMap.Rotate180(Dst: TByteMap);
  602. var
  603. Src: PByteArray;
  604. S, D: PByte;
  605. X, Y: Integer;
  606. T: Byte;
  607. begin
  608. if (Dst = nil) or (Dst = Self) then
  609. begin
  610. for Y := 0 to FHeight - 1 do
  611. begin
  612. Src := Scanline[Y];
  613. for X := 0 to (FWidth div 2) - 1 do
  614. begin
  615. T := Src^[X];
  616. Src^[X] := Src^[Width - 1 - X];
  617. Src^[Width - 1 - X] := T;
  618. end;
  619. end;
  620. end
  621. else
  622. begin
  623. S := PByte(FBits);
  624. D := PByte(@Dst.Bits[FHeight * FWidth - 1]);
  625. for X := 0 to FHeight * FWidth - 1 do
  626. begin
  627. D^ := S^;
  628. Dec(D);
  629. Inc(S);
  630. end;
  631. end;
  632. end;
  633. procedure TByteMap.Rotate270(Dst: TByteMap);
  634. var
  635. Src: PByteArray;
  636. Current: PByte;
  637. X, Y, W, H: Integer;
  638. begin
  639. if (Dst = nil) or (Dst = Self) then
  640. begin
  641. W := FWidth;
  642. H := FHeight;
  643. // inplace replace
  644. GetMem(Src, W * H);
  645. // copy bits
  646. Move(Bits^, Src^, W * H);
  647. SetSize(H, W);
  648. Current := PByte(Src);
  649. for Y := 0 to H - 1 do
  650. for X := 0 to W - 1 do
  651. begin
  652. Bits^[(W - 1 - X) * H + Y] := Current^;
  653. Inc(Current);
  654. end;
  655. // dispose old data pointer
  656. FreeMem(Src);
  657. end
  658. else
  659. begin
  660. // exchange dimensions
  661. Dst.SetSize(Height, Width);
  662. for Y := 0 to FHeight - 1 do
  663. begin
  664. Src := Scanline[Y];
  665. for X := 0 to FWidth - 1 do
  666. Dst.Bits^[X * FHeight + FHeight - 1 - Y] := Src^[X];
  667. end;
  668. end;
  669. end;
  670. procedure TByteMap.Rotate90(Dst: TByteMap);
  671. var
  672. Src: PByteArray;
  673. Current: PByte;
  674. X, Y, W, H: Integer;
  675. begin
  676. if (Dst = nil) or (Dst = Self) then
  677. begin
  678. W := FWidth;
  679. H := FHeight;
  680. // inplace replace
  681. GetMem(Src, W * H);
  682. // copy bits
  683. Move(Bits^, Src^, W * H);
  684. SetSize(H, W);
  685. Current := PByte(Src);
  686. for Y := 0 to H - 1 do
  687. for X := 0 to W - 1 do
  688. begin
  689. Bits^[X * H + (H - 1 - Y)] := Current^;
  690. Inc(Current);
  691. end;
  692. // dispose old data pointer
  693. FreeMem(Src);
  694. end
  695. else
  696. begin
  697. // exchange dimensions
  698. Dst.SetSize(Height, Width);
  699. for Y := 0 to FHeight - 1 do
  700. begin
  701. Src := Scanline[Y];
  702. for X := 0 to FWidth - 1 do
  703. Dst.Bits^[(FWidth - 1 - X) * FHeight + Y] := Src^[X];
  704. end;
  705. end;
  706. end;
  707. procedure TByteMap.SetValue(X, Y: Integer; Value: Byte);
  708. begin
  709. FBits^[X + Y * Width] := Value;
  710. end;
  711. procedure TByteMap.WriteTo(Dest: TCustomBitmap32; Conversion: TConversionType);
  712. var
  713. W, H, I, N: Integer;
  714. DstC: PColor32;
  715. DstB, SrcB: PByte;
  716. Resized: Boolean;
  717. begin
  718. Dest.BeginUpdate;
  719. Resized := False;
  720. try
  721. Resized := Dest.SetSize(Width, Height);
  722. if Empty then
  723. Exit;
  724. W := Width;
  725. H := Height;
  726. N := W * H - 1;
  727. SrcB := @FBits^;
  728. case Conversion of
  729. ctRed,
  730. ctGreen,
  731. ctBlue,
  732. ctAlpha:
  733. begin
  734. case Conversion of
  735. ctRed:
  736. DstB := @(PColor32Entry(Dest.Bits).R);
  737. ctGreen:
  738. DstB := @(PColor32Entry(Dest.Bits).G);
  739. ctBlue:
  740. DstB := @(PColor32Entry(Dest.Bits).B);
  741. ctAlpha:
  742. DstB := @(PColor32Entry(Dest.Bits).A);
  743. else
  744. DstB := nil;
  745. end;
  746. for I := 0 to N do
  747. begin
  748. DstB^ := SrcB^;
  749. Inc(DstB, SizeOf(TColor32));
  750. Inc(SrcB);
  751. end;
  752. end;
  753. ctUniformRGB,
  754. ctWeightedRGB:
  755. begin
  756. DstC := PColor32(Dest.Bits);
  757. for I := 0 to N do
  758. begin
  759. DstC^ := Gray32(SrcB^);
  760. Inc(DstC);
  761. Inc(SrcB);
  762. end;
  763. end;
  764. end;
  765. Dest.Changed;
  766. finally
  767. Dest.EndUpdate;
  768. if Resized then
  769. Dest.Resized;
  770. end;
  771. end;
  772. procedure TByteMap.WriteTo(Dest: TCustomBitmap32; const Palette: TPalette32);
  773. var
  774. W, H, I, N: Integer;
  775. DstC: PColor32;
  776. SrcB: PByte;
  777. begin
  778. Dest.BeginUpdate;
  779. try
  780. Dest.SetSize(Width, Height);
  781. if Empty then Exit;
  782. W := Width;
  783. H := Height;
  784. N := W * H - 1;
  785. DstC := Dest.PixelPtr[0, 0];
  786. SrcB := @FBits^;
  787. for I := 0 to N do
  788. begin
  789. DstC^ := Palette[SrcB^];
  790. Inc(DstC);
  791. Inc(SrcB);
  792. end;
  793. finally
  794. Dest.EndUpdate;
  795. Dest.Changed;
  796. end;
  797. end;
  798. procedure TByteMap.DrawTo(Dest: TCustomBitmap32; X, Y: Integer; Color: TColor32);
  799. var
  800. ClipRect: TRect;
  801. IX, IY: Integer;
  802. RGB: Cardinal;
  803. NewColor: TColor32;
  804. ScnLn: PColor32Array;
  805. ByteLine: PByteArray;
  806. Alpha: Byte;
  807. begin
  808. with ClipRect do
  809. begin
  810. Left := X;
  811. if Left < 0 then
  812. Left := 0;
  813. Top := Y;
  814. if Top < 0 then
  815. Top := 0;
  816. Right := X + Self.Width;
  817. if Right > Self.Width then
  818. Right := Self.Width;
  819. Bottom := Y + Self.Height;
  820. if Bottom > Self.Height then
  821. Bottom := Self.Height;
  822. // split RGB and alpha
  823. RGB := Color and $FFFFFF;
  824. Alpha := Color shr 24;
  825. // blend scanlines
  826. for IY := Top to Bottom - 1 do
  827. begin
  828. ScnLn := Dest.ScanLine[IY];
  829. ByteLine := Self.ScanLine[IY - Y];
  830. for IX := Left to Right - 1 do
  831. begin
  832. NewColor := (((ByteLine^[IX - X] * Alpha) shl 16) and $FF000000) or RGB;
  833. MergeMem(NewColor, ScnLn^[IX]);
  834. end;
  835. end;
  836. end;
  837. end;
  838. procedure TByteMap.DrawTo(Dest: TCustomBitmap32; Rect: TRect; Color: TColor32);
  839. var
  840. ClipRect: TRect;
  841. IX, IY: Integer;
  842. RGB: Cardinal;
  843. NewColor: TColor32;
  844. ScnLn: PColor32Array;
  845. ByteLine: PByteArray;
  846. Alpha: Byte;
  847. begin
  848. with ClipRect do
  849. begin
  850. Left := Rect.Left;
  851. if Left < 0 then
  852. Left := 0;
  853. Top := Rect.Top;
  854. if Top < 0 then
  855. Top := 0;
  856. Right := Math.Min(Rect.Left + Self.Width, Rect.Right);
  857. Bottom := Math.Min(Rect.Top + Self.Height, Rect.Bottom);
  858. // split RGB and alpha
  859. RGB := Color and $FFFFFF;
  860. Alpha := Color shr 24;
  861. // blend scanlines
  862. for IY := Top to Bottom - 1 do
  863. begin
  864. ScnLn := Dest.ScanLine[IY];
  865. ByteLine := Self.ScanLine[IY - Rect.Top];
  866. for IX := Left to Right - 1 do
  867. begin
  868. NewColor := (((ByteLine^[IX - Rect.Left] * Alpha) shl 16) and $FF000000) or RGB;
  869. MergeMem(NewColor, ScnLn^[IX]);
  870. end;
  871. end;
  872. end;
  873. end;
  874. { TWordMap }
  875. constructor TWordMap.Create;
  876. begin
  877. FBits := nil;
  878. inherited Create;
  879. end;
  880. destructor TWordMap.Destroy;
  881. begin
  882. FreeMem(FBits);
  883. inherited;
  884. end;
  885. procedure TWordMap.ChangeSize(var Width, Height: Integer; NewWidth,
  886. NewHeight: Integer);
  887. begin
  888. ReallocMem(FBits, NewWidth * NewHeight * SizeOf(Word));
  889. Width := NewWidth;
  890. Height := NewHeight;
  891. end;
  892. procedure TWordMap.Clear(FillValue: Word);
  893. begin
  894. FillWord(FBits^, Width * Height, FillValue);
  895. Changed;
  896. end;
  897. procedure TWordMap.Assign(Source: TPersistent);
  898. begin
  899. BeginUpdate;
  900. try
  901. if Source is TWordMap then
  902. begin
  903. inherited SetSize(TWordMap(Source).Width, TWordMap(Source).Height);
  904. Move(TWordMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(Word));
  905. end
  906. //else if Source is TBitmap32 then
  907. // ReadFrom(TBitmap32(Source), ctWeightedRGB)
  908. else
  909. inherited;
  910. finally
  911. EndUpdate;
  912. Changed;
  913. end;
  914. end;
  915. function TWordMap.Empty: Boolean;
  916. begin
  917. Result := not Assigned(FBits);
  918. end;
  919. function TWordMap.GetScanline(Y: Integer): PWordArray;
  920. begin
  921. Result := @FBits^[Y * Width];
  922. end;
  923. function TWordMap.GetValPtr(X, Y: Integer): PWord;
  924. begin
  925. Result := @FBits^[X + Y * Width];
  926. end;
  927. function TWordMap.GetValue(X, Y: Integer): Word;
  928. begin
  929. Result := FBits^[X + Y * Width];
  930. end;
  931. procedure TWordMap.SetValue(X, Y: Integer; const Value: Word);
  932. begin
  933. FBits^[X + Y * Width] := Value;
  934. end;
  935. { TIntegerMap }
  936. constructor TIntegerMap.Create;
  937. begin
  938. FBits := nil;
  939. inherited Create;
  940. end;
  941. destructor TIntegerMap.Destroy;
  942. begin
  943. FreeMem(FBits);
  944. inherited;
  945. end;
  946. procedure TIntegerMap.ChangeSize(var Width, Height: Integer; NewWidth,
  947. NewHeight: Integer);
  948. begin
  949. ReallocMem(FBits, NewWidth * NewHeight * SizeOf(Integer));
  950. Width := NewWidth;
  951. Height := NewHeight;
  952. end;
  953. procedure TIntegerMap.Clear(FillValue: Integer);
  954. begin
  955. FillLongword(FBits^, Width * Height, FillValue);
  956. Changed;
  957. end;
  958. procedure TIntegerMap.Assign(Source: TPersistent);
  959. begin
  960. BeginUpdate;
  961. try
  962. if Source is TIntegerMap then
  963. begin
  964. inherited SetSize(TIntegerMap(Source).Width, TIntegerMap(Source).Height);
  965. Move(TIntegerMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(Integer));
  966. end
  967. //else if Source is TBitmap32 then
  968. // ReadFrom(TBitmap32(Source), ctWeightedRGB)
  969. else
  970. inherited;
  971. finally
  972. EndUpdate;
  973. Changed;
  974. end;
  975. end;
  976. function TIntegerMap.Empty: Boolean;
  977. begin
  978. Result := not Assigned(FBits);
  979. end;
  980. function TIntegerMap.GetScanline(Y: Integer): PIntegerArray;
  981. begin
  982. Result := @FBits^[Y * Width];
  983. end;
  984. function TIntegerMap.GetValPtr(X, Y: Integer): PInteger;
  985. begin
  986. Result := @FBits^[X + Y * Width];
  987. end;
  988. function TIntegerMap.GetValue(X, Y: Integer): Integer;
  989. begin
  990. Result := FBits^[X + Y * Width];
  991. end;
  992. procedure TIntegerMap.SetValue(X, Y: Integer; const Value: Integer);
  993. begin
  994. FBits^[X + Y * Width] := Value;
  995. end;
  996. { TCardinalMap }
  997. constructor TCardinalMap.Create;
  998. begin
  999. FBits := nil;
  1000. inherited Create;
  1001. end;
  1002. destructor TCardinalMap.Destroy;
  1003. begin
  1004. FreeMem(FBits);
  1005. inherited;
  1006. end;
  1007. procedure TCardinalMap.Assign(Source: TPersistent);
  1008. begin
  1009. BeginUpdate;
  1010. try
  1011. if Source is TCardinalMap then
  1012. begin
  1013. inherited SetSize(TCardinalMap(Source).Width, TCardinalMap(Source).Height);
  1014. Move(TCardinalMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(Cardinal));
  1015. end
  1016. //else if Source is TBitmap32 then
  1017. // ReadFrom(TBitmap32(Source), ctWeightedRGB)
  1018. else
  1019. inherited;
  1020. finally
  1021. EndUpdate;
  1022. Changed;
  1023. end;
  1024. end;
  1025. procedure TCardinalMap.ChangeSize(var Width, Height: Integer; NewWidth,
  1026. NewHeight: Integer);
  1027. begin
  1028. ReallocMem(FBits, NewWidth * NewHeight * SizeOf(Cardinal));
  1029. Width := NewWidth;
  1030. Height := NewHeight;
  1031. end;
  1032. procedure TCardinalMap.Clear(FillValue: Cardinal);
  1033. begin
  1034. FillLongword(FBits^, Width * Height, FillValue);
  1035. Changed;
  1036. end;
  1037. function TCardinalMap.Empty: Boolean;
  1038. begin
  1039. Result := not Assigned(FBits);
  1040. end;
  1041. function TCardinalMap.GetScanline(Y: Integer): PCardinalArray;
  1042. begin
  1043. Result := @FBits^[Y * Width];
  1044. end;
  1045. function TCardinalMap.GetValPtr(X, Y: Cardinal): PCardinal;
  1046. begin
  1047. Result := @FBits^[X + Y * Cardinal(Width)];
  1048. end;
  1049. function TCardinalMap.GetValue(X, Y: Cardinal): Cardinal;
  1050. begin
  1051. Result := FBits^[X + Y * Cardinal(Width)];
  1052. end;
  1053. procedure TCardinalMap.SetValue(X, Y: Cardinal; const Value: Cardinal);
  1054. begin
  1055. FBits^[X + Y * Cardinal(Width)] := Value;
  1056. end;
  1057. { TFloatMap }
  1058. constructor TFloatMap.Create;
  1059. begin
  1060. FBits := nil;
  1061. inherited Create;
  1062. end;
  1063. destructor TFloatMap.Destroy;
  1064. begin
  1065. FreeMem(FBits);
  1066. inherited;
  1067. end;
  1068. procedure TFloatMap.Assign(Source: TPersistent);
  1069. begin
  1070. BeginUpdate;
  1071. try
  1072. if Source is TFloatMap then
  1073. begin
  1074. inherited SetSize(TFloatMap(Source).Width, TFloatMap(Source).Height);
  1075. Move(TFloatMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(TFloat));
  1076. end
  1077. //else if Source is TBitmap32 then
  1078. // ReadFrom(TBitmap32(Source), ctWeightedRGB)
  1079. else
  1080. inherited;
  1081. finally
  1082. EndUpdate;
  1083. Changed;
  1084. end;
  1085. end;
  1086. procedure TFloatMap.ChangeSize(var Width, Height: Integer; NewWidth,
  1087. NewHeight: Integer);
  1088. begin
  1089. ReallocMem(FBits, NewWidth * NewHeight * SizeOf(TFloat));
  1090. Width := NewWidth;
  1091. Height := NewHeight;
  1092. end;
  1093. procedure TFloatMap.Clear;
  1094. begin
  1095. FillChar(FBits^, Width * Height * SizeOf(TFloat), 0);
  1096. Changed;
  1097. end;
  1098. procedure TFloatMap.Clear(FillValue: TFloat);
  1099. var
  1100. Index: Integer;
  1101. begin
  1102. for Index := 0 to Width * Height - 1 do
  1103. FBits^[Index] := FillValue;
  1104. Changed;
  1105. end;
  1106. function TFloatMap.Empty: Boolean;
  1107. begin
  1108. Result := not Assigned(FBits);
  1109. end;
  1110. function TFloatMap.GetScanline(Y: Integer): PFloatArray;
  1111. begin
  1112. Result := @FBits^[Y * Width];
  1113. end;
  1114. function TFloatMap.GetValPtr(X, Y: Integer): GR32.PFloat;
  1115. begin
  1116. Result := @FBits^[X + Y * Width];
  1117. end;
  1118. function TFloatMap.GetValue(X, Y: Integer): TFloat;
  1119. begin
  1120. Result := FBits^[X + Y * Width];
  1121. end;
  1122. procedure TFloatMap.SetValue(X, Y: Integer; const Value: TFloat);
  1123. begin
  1124. FBits^[X + Y * Width] := Value;
  1125. end;
  1126. { TGenericMap<T> }
  1127. constructor TGenericMap<T>.Create;
  1128. begin
  1129. FBits := nil;
  1130. inherited Create;
  1131. end;
  1132. destructor TGenericMap<T>.Destroy;
  1133. begin
  1134. FreeMem(FBits);
  1135. inherited;
  1136. end;
  1137. procedure TGenericMap<T>.Assign(Source: TPersistent);
  1138. begin
  1139. BeginUpdate;
  1140. try
  1141. (*
  1142. if Source is TFloatMap then
  1143. begin
  1144. inherited SetSize(TFloatMap(Source).Width, TFloatMap(Source).Height);
  1145. Move(TFloatMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(TFloat));
  1146. end
  1147. //else if Source is TBitmap32 then
  1148. // ReadFrom(TBitmap32(Source), ctWeightedRGB)
  1149. else
  1150. inherited;
  1151. *)
  1152. finally
  1153. EndUpdate;
  1154. Changed;
  1155. end;
  1156. end;
  1157. procedure TGenericMap<T>.ChangeSize(var Width, Height: Integer; NewWidth,
  1158. NewHeight: Integer);
  1159. begin
  1160. ReallocMem(FBits, NewWidth * NewHeight * SizeOf(T));
  1161. Width := NewWidth;
  1162. Height := NewHeight;
  1163. end;
  1164. procedure TGenericMap<T>.Clear(FillValue: T);
  1165. var
  1166. Index: Integer;
  1167. begin
  1168. for Index := 0 to Width * Height - 1 do
  1169. Move(FillValue, PByte(FBits)[Index], SizeOf(T));
  1170. Changed;
  1171. end;
  1172. procedure TGenericMap<T>.Clear;
  1173. begin
  1174. FillChar(FBits^, Width * Height * SizeOf(T), 0);
  1175. Changed;
  1176. end;
  1177. function TGenericMap<T>.Empty: Boolean;
  1178. begin
  1179. Result := not Assigned(FBits);
  1180. end;
  1181. function TGenericMap<T>.GetValue(X, Y: Integer): T;
  1182. begin
  1183. Move(PByte(FBits)[(X + Y * Width) * SizeOf(T)], Result, SizeOf(T));
  1184. end;
  1185. procedure TGenericMap<T>.SetValue(X, Y: Integer; const Value: T);
  1186. begin
  1187. Move(Value, PByte(FBits)[(X + Y * Width) * SizeOf(T)], SizeOf(T));
  1188. end;
  1189. end.