GR32_OrdinalMaps.pas 32 KB

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