Ignore:
Timestamp:
Apr 17, 2019, 10:42:18 AM (5 years ago)
Author:
chronos
Message:
  • Modified: Updated Graphics32 library.
Location:
GraphicTest/Packages/Graphics32
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • GraphicTest/Packages/Graphics32

    • Property svn:ignore set to
      lib
  • GraphicTest/Packages/Graphics32/GR32_OrdinalMaps.pas

    r450 r522  
    5454    ctWeightedRGB);
    5555
     56{$IFDEF FPC}
     57  PInteger = ^Integer;
     58{$ENDIF}
     59
    5660  TBooleanMap = class(TCustomMap)
    5761  private
    58     FBits: TArrayOfByte;
    5962    function GetValue(X, Y: Integer): Boolean;
    6063    procedure SetValue(X, Y: Integer; const Value: Boolean);
    61     function GetBits: PByteArray;
    6264  protected
     65    FBits: PByteArray;
    6366    procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
    6467  public
     68    constructor Create; overload; override;
    6569    destructor Destroy; override;
     70
    6671    function Empty: Boolean; override;
    6772    procedure Clear(FillValue: Byte);
    6873    procedure ToggleBit(X, Y: Integer);
     74
    6975    property Value[X, Y: Integer]: Boolean read GetValue write SetValue; default;
    70     property Bits: PByteArray read GetBits;
     76    property Bits: PByteArray read FBits;
    7177  end;
    7278
    7379  TByteMap = class(TCustomMap)
    7480  private
    75     FBits: TArrayOfByte;
    7681    function GetValue(X, Y: Integer): Byte; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    7782    function GetValPtr(X, Y: Integer): PByte; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    7883    procedure SetValue(X, Y: Integer; Value: Byte); {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    79     function GetBits: PByteArray;
     84    function GetScanline(Y: Integer): PByteArray;
    8085  protected
     86    FBits: PByteArray;
    8187    procedure AssignTo(Dst: TPersistent); override;
    8288    procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
    8389  public
     90    constructor Create; overload; override;
    8491    destructor Destroy; override;
     92
    8593    procedure Assign(Source: TPersistent); override;
    86     function  Empty: Boolean; override;
     94    function Empty: Boolean; override;
    8795    procedure Clear(FillValue: Byte);
     96
     97    procedure Multiply(Value: Byte);
     98    procedure Add(Value: Byte);
     99    procedure Sub(Value: Byte);
     100
    88101    procedure ReadFrom(Source: TCustomBitmap32; Conversion: TConversionType);
    89102    procedure WriteTo(Dest: TCustomBitmap32; Conversion: TConversionType); overload;
    90103    procedure WriteTo(Dest: TCustomBitmap32; const Palette: TPalette32); overload;
    91     property Bits: PByteArray read GetBits;
     104
     105    procedure DrawTo(Dest: TCustomBitmap32; X, Y: Integer; Color: TColor32); overload;
     106    procedure DrawTo(Dest: TCustomBitmap32; Rect: TRect; Color: TColor32); overload;
     107
     108    procedure Downsample(Factor: Byte); overload;
     109    procedure Downsample(Dest: TByteMap; Factor: Byte); overload;
     110
     111    procedure FlipHorz(Dst: TByteMap = nil);
     112    procedure FlipVert(Dst: TByteMap = nil);
     113    procedure Rotate90(Dst: TByteMap = nil);
     114    procedure Rotate180(Dst: TByteMap = nil);
     115    procedure Rotate270(Dst: TByteMap = nil);
     116
     117    property Bits: PByteArray read FBits;
     118    property Scanline[Y: Integer]: PByteArray read GetScanline;
    92119    property ValPtr[X, Y: Integer]: PByte read GetValPtr;
    93120    property Value[X, Y: Integer]: Byte read GetValue write SetValue; default;
    94121  end;
    95122
     123  { TWordMap }
     124
    96125  TWordMap = class(TCustomMap)
    97126  private
    98     FBits: TArrayOfWord;
    99127    function GetValPtr(X, Y: Integer): PWord; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    100128    function GetValue(X, Y: Integer): Word; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    101129    procedure SetValue(X, Y: Integer; const Value: Word); {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    102     function GetBits: PWordArray;
     130    function GetScanline(Y: Integer): PWordArray;
    103131  protected
     132    FBits: PWordArray;
    104133    procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
    105134  public
     135    constructor Create; overload; override;
    106136    destructor Destroy; override;
     137
     138    procedure Assign(Source: TPersistent); override;
    107139    function Empty: Boolean; override;
    108140    procedure Clear(FillValue: Word);
     141
    109142    property ValPtr[X, Y: Integer]: PWord read GetValPtr;
    110143    property Value[X, Y: Integer]: Word read GetValue write SetValue; default;
    111     property Bits: PWordArray read GetBits;
    112   end;
     144    property Bits: PWordArray read FBits;
     145    property Scanline[Y: Integer]: PWordArray read GetScanline;
     146  end;
     147
     148  { TIntegerMap }
    113149
    114150  TIntegerMap = class(TCustomMap)
    115151  private
    116     FBits: TArrayOfInteger;
    117152    function GetValPtr(X, Y: Integer): PInteger; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    118153    function GetValue(X, Y: Integer): Integer; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    119154    procedure SetValue(X, Y: Integer; const Value: Integer); {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    120     function GetBits: PIntegerArray;
     155    function GetScanline(Y: Integer): PIntegerArray;
    121156  protected
     157    FBits: PIntegerArray;
    122158    procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
    123159  public
     160    constructor Create; overload; override;
    124161    destructor Destroy; override;
     162
     163    procedure Assign(Source: TPersistent); override;
    125164    function Empty: Boolean; override;
    126     procedure Clear(FillValue: Integer);
     165    procedure Clear(FillValue: Integer = 0);
     166
    127167    property ValPtr[X, Y: Integer]: PInteger read GetValPtr;
    128168    property Value[X, Y: Integer]: Integer read GetValue write SetValue; default;
    129     property Bits: PIntegerArray read GetBits;
    130   end;
     169    property Bits: PIntegerArray read FBits;
     170    property Scanline[Y: Integer]: PIntegerArray read GetScanline;
     171  end;
     172
     173  { TCardinalMap }
     174
     175  TCardinalMap = class(TCustomMap)
     176  private
     177    function GetValPtr(X, Y: Cardinal): PCardinal; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
     178    function GetValue(X, Y: Cardinal): Cardinal; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
     179    procedure SetValue(X, Y: Cardinal; const Value: Cardinal); {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
     180    function GetScanline(Y: Integer): PCardinalArray;
     181  protected
     182    FBits: PCardinalArray;
     183    procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
     184  public
     185    constructor Create; overload; override;
     186    destructor Destroy; override;
     187
     188    procedure Assign(Source: TPersistent); override;
     189    function Empty: Boolean; override;
     190    procedure Clear(FillValue: Cardinal = 0);
     191
     192    property ValPtr[X, Y: Cardinal]: PCardinal read GetValPtr;
     193    property Value[X, Y: Cardinal]: Cardinal read GetValue write SetValue; default;
     194    property Bits: PCardinalArray read FBits;
     195    property Scanline[Y: Integer]: PCardinalArray read GetScanline;
     196  end;
     197
     198  { TFloatMap }
    131199
    132200  TFloatMap = class(TCustomMap)
    133201  private
    134     FBits: TArrayOfFloat;
    135     function GetValPtr(X, Y: Integer): PFloat; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
     202    function GetValPtr(X, Y: Integer): GR32.PFloat; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    136203    function GetValue(X, Y: Integer): TFloat; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    137204    procedure SetValue(X, Y: Integer; const Value: TFloat); {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
    138     function GetBits: PFloatArray;
     205    function GetScanline(Y: Integer): PFloatArray;
    139206  protected
     207    FBits: PFloatArray;
    140208    procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
    141209  public
     210    constructor Create; overload; override;
    142211    destructor Destroy; override;
     212
     213    procedure Assign(Source: TPersistent); override;
    143214    function Empty: Boolean; override;
    144215    procedure Clear; overload;
    145216    procedure Clear(FillValue: TFloat); overload;
     217
    146218    property ValPtr[X, Y: Integer]: PFloat read GetValPtr;
    147219    property Value[X, Y: Integer]: TFloat read GetValue write SetValue; default;
    148     property Bits: PFloatArray read GetBits;
    149   end;
     220    property Bits: PFloatArray read FBits;
     221    property Scanline[Y: Integer]: PFloatArray read GetScanline;
     222  end;
     223
     224{$IFDEF COMPILER2010}
     225
     226  { TGenericMap<T> }
     227
     228  TGenericMap<T> = class(TCustomMap)
     229  private
     230    function GetValue(X, Y: Integer): T; {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
     231    procedure SetValue(X, Y: Integer; const Value: T); {$IFDEF INLININGSUPPORTED} inline; {$ENDIF}
     232  protected
     233    FBits: Pointer;
     234    procedure ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer); override;
     235  public
     236    constructor Create; overload; override;
     237    destructor Destroy; override;
     238
     239    procedure Assign(Source: TPersistent); override;
     240    function Empty: Boolean; override;
     241    procedure Clear; overload;
     242    procedure Clear(FillValue: T); overload;
     243
     244    property Value[X, Y: Integer]: T read GetValue write SetValue; default;
     245    property Bits: Pointer read FBits;
     246  end;
     247
     248{$ENDIF}
    150249
    151250implementation
    152251
    153252uses
    154   GR32_LowLevel;
     253  Math, GR32_LowLevel, GR32_Blend, GR32_Resamplers;
     254
     255function Bytes(Bits: Integer): Integer;
     256begin
     257  Result := (Bits - 1) shr 3 + 1;
     258end;
    155259
    156260{ TBooleanMap }
    157261
    158 function Bytes(Bits: Integer): Integer;
    159 begin
    160   Result := (Bits - 1) shr 3 + 1;
     262constructor TBooleanMap.Create;
     263begin
     264  FreeMem(FBits);
     265  inherited Create;
    161266end;
    162267
     
    164269  NewHeight: Integer);
    165270begin
    166   SetLength(FBits, Bytes(NewWidth * NewHeight));
     271  ReallocMem(FBits, Bytes(NewWidth * NewHeight));
    167272  Width := NewWidth;
    168273  Height := NewHeight;
     
    171276procedure TBooleanMap.Clear(FillValue: Byte);
    172277begin
    173   FillChar(FBits[0], Bytes(Width * Height), FillValue);
     278  FillChar(FBits^, Bytes(Width * Height), FillValue);
    174279end;
    175280
     
    185290end;
    186291
    187 function TBooleanMap.GetBits: PByteArray;
    188 begin
    189   Result := @FBits[0];
    190 end;
    191 
    192292function TBooleanMap.GetValue(X, Y: Integer): Boolean;
    193293begin
    194294  X := X + Y * Width;
    195   Result := FBits[X shr 3] and (1 shl (X and 7)) <> 0; //Boolean(FBits[X shr 3] and (1 shl (X and 7)));
     295  Result := FBits^[X shr 3] and (1 shl (X and 7)) <> 0; //Boolean(FBits^[X shr 3] and (1 shl (X and 7)));
    196296end;
    197297
     
    200300  X := Y * Width + X;
    201301  if Value then
    202     FBits[X shr 3] := FBits[X shr 3] or (1 shl (X and 7))
     302    FBits^[X shr 3] := FBits^[X shr 3] or (1 shl (X and 7))
    203303  else
    204     FBits[X shr 3] := FBits[X shr 3] and ((1 shl (X and 7)) xor $FF);
     304    FBits^[X shr 3] := FBits^[X shr 3] and ((1 shl (X and 7)) xor $FF);
    205305end;
    206306
     
    208308begin
    209309  X := Y * Width + X;
    210   FBits[X shr 3] := FBits[X shr 3] xor (1 shl (X and 7));
     310  FBits^[X shr 3] := FBits^[X shr 3] xor (1 shl (X and 7));
    211311end;
    212312
    213313{ TByteMap }
     314
     315constructor TByteMap.Create;
     316begin
     317  FBits := nil;
     318  inherited Create;
     319end;
     320
     321destructor TByteMap.Destroy;
     322begin
     323  FreeMem(FBits);
     324  inherited;
     325end;
     326
     327procedure TByteMap.Downsample(Factor: Byte);
     328begin
     329  // downsample inplace
     330  case Factor of
     331    2:
     332      DownsampleByteMap2x(Self, Self);
     333    3:
     334      DownsampleByteMap3x(Self, Self);
     335    4:
     336      DownsampleByteMap4x(Self, Self);
     337    6:
     338      begin
     339        DownsampleByteMap3x(Self, Self);
     340        DownsampleByteMap2x(Self, Self);
     341      end;
     342    8:
     343      begin
     344        DownsampleByteMap4x(Self, Self);
     345        DownsampleByteMap2x(Self, Self);
     346      end;
     347    9:
     348      begin
     349        DownsampleByteMap3x(Self, Self);
     350        DownsampleByteMap3x(Self, Self);
     351      end;
     352    12:
     353      begin
     354        DownsampleByteMap4x(Self, Self);
     355        DownsampleByteMap3x(Self, Self);
     356      end;
     357    16:
     358      begin
     359        DownsampleByteMap4x(Self, Self);
     360        DownsampleByteMap4x(Self, Self);
     361      end;
     362    18:
     363      begin
     364        DownsampleByteMap3x(Self, Self);
     365        DownsampleByteMap3x(Self, Self);
     366        DownsampleByteMap2x(Self, Self);
     367      end;
     368    24:
     369      begin
     370        DownsampleByteMap4x(Self, Self);
     371        DownsampleByteMap3x(Self, Self);
     372        DownsampleByteMap2x(Self, Self);
     373      end;
     374    27:
     375      begin
     376        DownsampleByteMap3x(Self, Self);
     377        DownsampleByteMap3x(Self, Self);
     378        DownsampleByteMap3x(Self, Self);
     379      end;
     380    32:
     381      begin
     382        DownsampleByteMap4x(Self, Self);
     383        DownsampleByteMap4x(Self, Self);
     384        DownsampleByteMap2x(Self, Self);
     385      end;
     386  end;
     387end;
     388
     389procedure TByteMap.Downsample(Dest: TByteMap; Factor: Byte);
     390
     391  procedure DownsampleAndMove;
     392  var
     393    Temp: TByteMap;
     394    Y: Integer;
     395  begin
     396    // clone destination and downsample inplace
     397    Temp := TByteMap.Create;
     398    Temp.Assign(Self);
     399    Temp.Downsample(Factor);
     400
     401    // copy downsampled result
     402    Dest.SetSize(Width div Factor, Height div Factor);
     403    for Y := 0 to Dest.Height - 1 do
     404      Move(Temp.Scanline[Y]^, Dest.Scanline[Y]^, Dest.Width);
     405  end;
     406
     407begin
     408  // downsample directly
     409  if (Dest = Self) or not (Factor in [2, 3, 4]) then
     410  begin
     411    DownsampleAndMove;
     412    Exit;
     413  end;
     414
     415  case Factor of
     416    2:
     417      begin
     418        Dest.SetSize(Width div 2, Height div 2);
     419        DownsampleByteMap2x(Self, Dest);
     420      end;
     421    3:
     422      begin
     423        // downsample directly
     424        Dest.SetSize(Width div 3, Height div 3);
     425        DownsampleByteMap3x(Self, Dest);
     426      end;
     427    4:
     428      begin
     429        // downsample directly
     430        Dest.SetSize(Width div 4, Height div 4);
     431        DownsampleByteMap4x(Self, Dest);
     432      end;
     433  end;
     434end;
    214435
    215436procedure TByteMap.Assign(Source: TPersistent);
     
    240461procedure TByteMap.ChangeSize(var Width, Height: Integer; NewWidth, NewHeight: Integer);
    241462begin
    242   SetLength(FBits, NewWidth * NewHeight);
     463  ReallocMem(FBits, NewWidth * NewHeight);
    243464  Width := NewWidth;
    244465  Height := NewHeight;
     
    247468procedure TByteMap.Clear(FillValue: Byte);
    248469begin
    249   FillChar(Bits[0], Width * Height, FillValue);
     470  FillChar(Bits^, Width * Height, FillValue);
    250471  Changed;
    251 end;
    252 
    253 destructor TByteMap.Destroy;
    254 begin
    255   FBits := nil;
    256   inherited;
    257472end;
    258473
     
    263478end;
    264479
    265 function TByteMap.GetBits: PByteArray;
    266 begin
    267   Result := @FBits[0];
     480procedure TByteMap.FlipHorz(Dst: TByteMap);
     481var
     482  i, j: Integer;
     483  P1, P2: PByte;
     484  tmp: Byte;
     485  W, W2: Integer;
     486begin
     487  W := Width;
     488  if (Dst = nil) or (Dst = Self) then
     489  begin
     490    { In-place flipping }
     491    P1 := PByte(Bits);
     492    P2 := P1;
     493    Inc(P2, Width - 1);
     494    W2 := Width shr 1;
     495    for J := 0 to Height - 1 do
     496    begin
     497      for I := 0 to W2 - 1 do
     498      begin
     499        tmp := P1^;
     500        P1^ := P2^;
     501        P2^ := tmp;
     502        Inc(P1);
     503        Dec(P2);
     504      end;
     505      Inc(P1, W - W2);
     506      Inc(P2, W + W2);
     507    end;
     508    Changed;
     509  end
     510  else
     511  begin
     512    { Flip to Dst }
     513    Dst.BeginUpdate;
     514    Dst.SetSize(W, Height);
     515    P1 := PByte(Bits);
     516    P2 := PByte(Dst.Bits);
     517    Inc(P2, W - 1);
     518    for J := 0 to Height - 1 do
     519    begin
     520      for I := 0 to W - 1 do
     521      begin
     522        P2^ := P1^;
     523        Inc(P1);
     524        Dec(P2);
     525      end;
     526      Inc(P2, W shl 1);
     527    end;
     528    Dst.EndUpdate;
     529    Dst.Changed;
     530  end;
     531end;
     532
     533procedure TByteMap.FlipVert(Dst: TByteMap);
     534var
     535  J, J2: Integer;
     536  Buffer: PByteArray;
     537  P1, P2: PByte;
     538begin
     539  if (Dst = nil) or (Dst = Self) then
     540  begin
     541    { in-place }
     542    J2 := Height - 1;
     543    GetMem(Buffer, Width);
     544    for J := 0 to Height div 2 - 1 do
     545    begin
     546      P1 := PByte(ScanLine[J]);
     547      P2 := PByte(ScanLine[J2]);
     548      Move(P1^, Buffer^, Width);
     549      Move(P2^, P1^, Width);
     550      Move(Buffer^, P2^, Width);
     551      Dec(J2);
     552    end;
     553    FreeMem(Buffer);
     554    Changed;
     555  end
     556  else
     557  begin
     558    Dst.SetSize(Width, Height);
     559    J2 := Height - 1;
     560    for J := 0 to Height - 1 do
     561    begin
     562      Move(ScanLine[J]^, Dst.ScanLine[J2]^, Width);
     563      Dec(J2);
     564    end;
     565    Dst.Changed;
     566  end;
     567end;
     568
     569function TByteMap.GetScanline(Y: Integer): PByteArray;
     570begin
     571  Result := @FBits^[Y * Width];
    268572end;
    269573
    270574function TByteMap.GetValPtr(X, Y: Integer): PByte;
    271575begin
    272   Result := @FBits[X + Y * Width];
     576  Result := @FBits^[X + Y * Width];
    273577end;
    274578
    275579function TByteMap.GetValue(X, Y: Integer): Byte;
    276580begin
    277   Result := FBits[X + Y * Width];
     581  Result := FBits^[X + Y * Width];
     582end;
     583
     584procedure TByteMap.Multiply(Value: Byte);
     585var
     586  Index: Integer;
     587begin
     588  for Index := 0 to FWidth * FHeight - 1 do
     589    FBits^[Index] := ((FBits^[Index] * Value + $80) shr 8);
     590end;
     591
     592procedure TByteMap.Add(Value: Byte);
     593var
     594  Index: Integer;
     595begin
     596  for Index := 0 to FWidth * FHeight - 1 do
     597    FBits^[Index] := Min(FBits^[Index] + Value, 255);
     598end;
     599
     600procedure TByteMap.Sub(Value: Byte);
     601var
     602  Index: Integer;
     603begin
     604  for Index := 0 to FWidth * FHeight - 1 do
     605    FBits^[Index] := Max(FBits^[Index] + Value, 0);
    278606end;
    279607
     
    295623    SrcC := Source.PixelPtr[0, 0];
    296624    SrcB := Pointer(SrcC);
    297     DstB := @FBits[0];
     625    DstB := @FBits^;
    298626    case Conversion of
    299627
     
    371699end;
    372700
     701procedure TByteMap.Rotate180(Dst: TByteMap);
     702var
     703  Src: PByteArray;
     704  S, D: PByte;
     705  X, Y: Integer;
     706  T: Byte;
     707begin
     708  if (Dst = nil) or (Dst = Self) then
     709  begin
     710    for Y := 0 to FHeight - 1 do
     711    begin
     712      Src := Scanline[Y];
     713      for X := 0 to (FWidth div 2) - 1 do
     714      begin
     715        T := Src^[X];
     716        Src^[X] := Src^[Width - 1 - X];
     717        Src^[Width - 1 - X] := T;
     718      end;
     719    end;
     720  end
     721  else
     722  begin
     723    S := PByte(FBits);
     724    D := PByte(@Dst.Bits[FHeight * FWidth - 1]);
     725    for X := 0 to FHeight * FWidth - 1 do
     726    begin
     727      D^ := S^;
     728      Dec(D);
     729      Inc(S);
     730    end;
     731  end;
     732end;
     733
     734procedure TByteMap.Rotate270(Dst: TByteMap);
     735var
     736  Src: PByteArray;
     737  Current: PByte;
     738  X, Y, W, H: Integer;
     739begin
     740  if (Dst = nil) or (Dst = Self) then
     741  begin
     742    W := FWidth;
     743    H := FHeight;
     744
     745     // inplace replace
     746    GetMem(Src, W * H);
     747
     748    // copy bits
     749    Move(Bits^, Src^, W * H);
     750
     751    SetSize(H, W);
     752
     753    Current := PByte(Src);
     754    for Y := 0 to H - 1 do
     755      for X := 0 to W - 1 do
     756      begin
     757        Bits^[(W - 1 - X) * H + Y] := Current^;
     758        Inc(Current);
     759      end;
     760
     761    // dispose old data pointer
     762    FreeMem(Src);
     763  end
     764  else
     765  begin
     766    // exchange dimensions
     767    Dst.SetSize(Height, Width);
     768
     769    for Y := 0 to FHeight - 1 do
     770    begin
     771      Src := Scanline[Y];
     772      for X := 0 to FWidth - 1 do
     773        Dst.Bits^[X * FHeight + FHeight - 1 - Y] := Src^[X];
     774    end;
     775  end;
     776end;
     777
     778procedure TByteMap.Rotate90(Dst: TByteMap);
     779var
     780  Src: PByteArray;
     781  Current: PByte;
     782  X, Y, W, H: Integer;
     783begin
     784  if (Dst = nil) or (Dst = Self) then
     785  begin
     786    W := FWidth;
     787    H := FHeight;
     788
     789     // inplace replace
     790    GetMem(Src, W * H);
     791
     792    // copy bits
     793    Move(Bits^, Src^, W * H);
     794
     795    SetSize(H, W);
     796
     797    Current := PByte(Src);
     798    for Y := 0 to H - 1 do
     799      for X := 0 to W - 1 do
     800      begin
     801        Bits^[X * H + (H - 1 - Y)] := Current^;
     802        Inc(Current);
     803      end;
     804
     805    // dispose old data pointer
     806    FreeMem(Src);
     807  end
     808  else
     809  begin
     810    // exchange dimensions
     811    Dst.SetSize(Height, Width);
     812
     813    for Y := 0 to FHeight - 1 do
     814    begin
     815      Src := Scanline[Y];
     816      for X := 0 to FWidth - 1 do
     817        Dst.Bits^[(FWidth - 1 - X) * FHeight + Y] := Src^[X];
     818    end;
     819  end;
     820end;
     821
    373822procedure TByteMap.SetValue(X, Y: Integer; Value: Byte);
    374823begin
    375   FBits[X + Y * Width] := Value;
     824  FBits^[X + Y * Width] := Value;
    376825end;
    377826
     
    394843    DstC := Dest.PixelPtr[0, 0];
    395844    DstB := Pointer(DstC);
    396     SrcB := @FBits[0];
     845    SrcB := @FBits^;
    397846    case Conversion of
    398847
     
    472921    N := W * H - 1;
    473922    DstC := Dest.PixelPtr[0, 0];
    474     SrcB := @FBits[0];
     923    SrcB := @FBits^;
    475924
    476925    for I := 0 to N do
     
    485934  end;
    486935end;
    487  
     936
     937procedure TByteMap.DrawTo(Dest: TCustomBitmap32; X, Y: Integer; Color: TColor32);
     938var
     939  ClipRect: TRect;
     940  IX, IY: Integer;
     941  RGB: Cardinal;
     942  NewColor: TColor32;
     943  ScnLn: PColor32Array;
     944  ByteLine: PByteArray;
     945  Alpha: Byte;
     946begin
     947  with ClipRect do
     948  begin
     949    Left := X;
     950    if Left < 0 then
     951      Left := 0;
     952    Top := Y;
     953    if Top < 0 then
     954      Top := 0;
     955    Right := X + Self.Width;
     956    if Right > Self.Width then
     957      Right := Self.Width;
     958    Bottom := Y + Self.Height;
     959    if Bottom > Self.Height then
     960      Bottom := Self.Height;
     961
     962    // split RGB and alpha
     963    RGB := Color and $FFFFFF;
     964    Alpha := Color shr 24;
     965
     966    // blend scanlines
     967    for IY := Top to Bottom - 1 do
     968    begin
     969      ScnLn := Dest.ScanLine[IY];
     970      ByteLine := Self.ScanLine[IY - Y];
     971      for IX := Left to Right - 1 do
     972      begin
     973        NewColor := (((ByteLine^[IX - X] * Alpha) shl 16) and $FF000000) or RGB;
     974        MergeMem(NewColor, ScnLn^[IX]);
     975      end;
     976    end;
     977    EMMS;
     978  end;
     979end;
     980
     981procedure TByteMap.DrawTo(Dest: TCustomBitmap32; Rect: TRect; Color: TColor32);
     982var
     983  ClipRect: TRect;
     984  IX, IY: Integer;
     985  RGB: Cardinal;
     986  NewColor: TColor32;
     987  ScnLn: PColor32Array;
     988  ByteLine: PByteArray;
     989  Alpha: Byte;
     990begin
     991  with ClipRect do
     992  begin
     993    Left := Rect.Left;
     994    if Left < 0 then
     995      Left := 0;
     996    Top := Rect.Top;
     997    if Top < 0 then
     998      Top := 0;
     999    Right := Math.Min(Rect.Left + Self.Width, Rect.Right);
     1000    Bottom := Math.Min(Rect.Top + Self.Height, Rect.Bottom);
     1001
     1002    // split RGB and alpha
     1003    RGB := Color and $FFFFFF;
     1004    Alpha := Color shr 24;
     1005
     1006    // blend scanlines
     1007    for IY := Top to Bottom - 1 do
     1008    begin
     1009      ScnLn := Dest.ScanLine[IY];
     1010      ByteLine := Self.ScanLine[IY - Rect.Top];
     1011      for IX := Left to Right - 1 do
     1012      begin
     1013        NewColor := (((ByteLine^[IX - Rect.Left] * Alpha) shl 16) and $FF000000) or RGB;
     1014        MergeMem(NewColor, ScnLn^[IX]);
     1015      end;
     1016    end;
     1017    EMMS;
     1018  end;
     1019end;
     1020
     1021
    4881022{ TWordMap }
     1023
     1024constructor TWordMap.Create;
     1025begin
     1026  FBits := nil;
     1027  inherited Create;
     1028end;
     1029
     1030destructor TWordMap.Destroy;
     1031begin
     1032  FreeMem(FBits);
     1033  inherited;
     1034end;
    4891035
    4901036procedure TWordMap.ChangeSize(var Width, Height: Integer; NewWidth,
    4911037  NewHeight: Integer);
    4921038begin
    493   SetLength(FBits, NewWidth * NewHeight);
     1039  ReallocMem(FBits, NewWidth * NewHeight * SizeOf(Word));
    4941040  Width := NewWidth;
    4951041  Height := NewHeight;
     
    4981044procedure TWordMap.Clear(FillValue: Word);
    4991045begin
    500   FillWord(FBits[0], Width * Height, FillValue);
     1046  FillWord(FBits^, Width * Height, FillValue);
    5011047  Changed;
    5021048end;
    5031049
    504 destructor TWordMap.Destroy;
     1050procedure TWordMap.Assign(Source: TPersistent);
     1051begin
     1052  BeginUpdate;
     1053    try
     1054      if Source is TWordMap then
     1055      begin
     1056        inherited SetSize(TWordMap(Source).Width, TWordMap(Source).Height);
     1057        Move(TWordMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(Word));
     1058      end
     1059      //else if Source is TBitmap32 then
     1060      //  ReadFrom(TBitmap32(Source), ctWeightedRGB)
     1061      else
     1062        inherited;
     1063    finally
     1064      EndUpdate;
     1065      Changed;
     1066    end;
     1067end;
     1068
     1069function TWordMap.Empty: Boolean;
     1070begin
     1071  Result := not Assigned(FBits);
     1072end;
     1073
     1074function TWordMap.GetScanline(Y: Integer): PWordArray;
     1075begin
     1076  Result := @FBits^[Y * Width];
     1077end;
     1078
     1079function TWordMap.GetValPtr(X, Y: Integer): PWord;
     1080begin
     1081  Result := @FBits^[X + Y * Width];
     1082end;
     1083
     1084function TWordMap.GetValue(X, Y: Integer): Word;
     1085begin
     1086  Result := FBits^[X + Y * Width];
     1087end;
     1088
     1089procedure TWordMap.SetValue(X, Y: Integer; const Value: Word);
     1090begin
     1091  FBits^[X + Y * Width] := Value;
     1092end;
     1093
     1094
     1095{ TIntegerMap }
     1096
     1097constructor TIntegerMap.Create;
    5051098begin
    5061099  FBits := nil;
     1100  inherited Create;
     1101end;
     1102
     1103destructor TIntegerMap.Destroy;
     1104begin
     1105  FreeMem(FBits);
    5071106  inherited;
    5081107end;
    509 
    510 function TWordMap.Empty: Boolean;
    511 begin
    512   Result := not Assigned(FBits);
    513 end;
    514 
    515 function TWordMap.GetBits: PWordArray;
    516 begin
    517   Result := @FBits[0];
    518 end;
    519 
    520 function TWordMap.GetValPtr(X, Y: Integer): PWord;
    521 begin
    522   Result := @FBits[X + Y * Width];
    523 end;
    524 
    525 function TWordMap.GetValue(X, Y: Integer): Word;
    526 begin
    527   Result := FBits[X + Y * Width];
    528 end;
    529 
    530 procedure TWordMap.SetValue(X, Y: Integer; const Value: Word);
    531 begin
    532   FBits[X + Y * Width] := Value;
    533 end;
    534 
    535 { TIntegerMap }
    5361108
    5371109procedure TIntegerMap.ChangeSize(var Width, Height: Integer; NewWidth,
    5381110  NewHeight: Integer);
    5391111begin
    540   SetLength(FBits, NewWidth * NewHeight);
     1112  ReallocMem(FBits, NewWidth * NewHeight * SizeOf(Integer));
    5411113  Width := NewWidth;
    5421114  Height := NewHeight;
     
    5451117procedure TIntegerMap.Clear(FillValue: Integer);
    5461118begin
    547   FillLongword(FBits[0], Width * Height, FillValue);
     1119  FillLongword(FBits^, Width * Height, FillValue);
    5481120  Changed;
    5491121end;
    5501122
    551 destructor TIntegerMap.Destroy;
     1123procedure TIntegerMap.Assign(Source: TPersistent);
     1124begin
     1125  BeginUpdate;
     1126  try
     1127    if Source is TIntegerMap then
     1128    begin
     1129      inherited SetSize(TIntegerMap(Source).Width, TIntegerMap(Source).Height);
     1130      Move(TIntegerMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(Integer));
     1131    end
     1132    //else if Source is TBitmap32 then
     1133    //  ReadFrom(TBitmap32(Source), ctWeightedRGB)
     1134    else
     1135      inherited;
     1136  finally
     1137    EndUpdate;
     1138    Changed;
     1139  end;
     1140end;
     1141
     1142function TIntegerMap.Empty: Boolean;
     1143begin
     1144  Result := not Assigned(FBits);
     1145end;
     1146
     1147function TIntegerMap.GetScanline(Y: Integer): PIntegerArray;
     1148begin
     1149  Result := @FBits^[Y * Width];
     1150end;
     1151
     1152function TIntegerMap.GetValPtr(X, Y: Integer): PInteger;
     1153begin
     1154  Result := @FBits^[X + Y * Width];
     1155end;
     1156
     1157function TIntegerMap.GetValue(X, Y: Integer): Integer;
     1158begin
     1159  Result := FBits^[X + Y * Width];
     1160end;
     1161
     1162procedure TIntegerMap.SetValue(X, Y: Integer; const Value: Integer);
     1163begin
     1164  FBits^[X + Y * Width] := Value;
     1165end;
     1166
     1167
     1168{ TCardinalMap }
     1169
     1170constructor TCardinalMap.Create;
    5521171begin
    5531172  FBits := nil;
     1173  inherited Create;
     1174end;
     1175
     1176destructor TCardinalMap.Destroy;
     1177begin
     1178  FreeMem(FBits);
    5541179  inherited;
    5551180end;
    5561181
    557 function TIntegerMap.Empty: Boolean;
     1182procedure TCardinalMap.Assign(Source: TPersistent);
     1183begin
     1184  BeginUpdate;
     1185  try
     1186    if Source is TCardinalMap then
     1187    begin
     1188      inherited SetSize(TCardinalMap(Source).Width, TCardinalMap(Source).Height);
     1189      Move(TCardinalMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(Cardinal));
     1190    end
     1191    //else if Source is TBitmap32 then
     1192    //  ReadFrom(TBitmap32(Source), ctWeightedRGB)
     1193    else
     1194      inherited;
     1195  finally
     1196    EndUpdate;
     1197    Changed;
     1198  end;
     1199end;
     1200
     1201procedure TCardinalMap.ChangeSize(var Width, Height: Integer; NewWidth,
     1202  NewHeight: Integer);
     1203begin
     1204  ReallocMem(FBits, NewWidth * NewHeight * SizeOf(Cardinal));
     1205  Width := NewWidth;
     1206  Height := NewHeight;
     1207end;
     1208
     1209procedure TCardinalMap.Clear(FillValue: Cardinal);
     1210begin
     1211  FillLongword(FBits^, Width * Height, FillValue);
     1212  Changed;
     1213end;
     1214
     1215function TCardinalMap.Empty: Boolean;
    5581216begin
    5591217  Result := not Assigned(FBits);
    5601218end;
    5611219
    562 function TIntegerMap.GetBits: PIntegerArray;
    563 begin
    564   Result := @FBits[0];
    565 end;
    566 
    567 function TIntegerMap.GetValPtr(X, Y: Integer): PInteger;
    568 begin
    569   Result := @FBits[X + Y * Width];
    570 end;
    571 
    572 function TIntegerMap.GetValue(X, Y: Integer): Integer;
    573 begin
    574   Result := FBits[X + Y * Width];
    575 end;
    576 
    577 procedure TIntegerMap.SetValue(X, Y: Integer; const Value: Integer);
    578 begin
    579   FBits[X + Y * Width] := Value;
    580 end;
     1220function TCardinalMap.GetScanline(Y: Integer): PCardinalArray;
     1221begin
     1222  Result := @FBits^[Y * Width];
     1223end;
     1224
     1225function TCardinalMap.GetValPtr(X, Y: Cardinal): PCardinal;
     1226begin
     1227  Result := @FBits^[X + Y * Cardinal(Width)];
     1228end;
     1229
     1230function TCardinalMap.GetValue(X, Y: Cardinal): Cardinal;
     1231begin
     1232  Result := FBits^[X + Y * Cardinal(Width)];
     1233end;
     1234
     1235procedure TCardinalMap.SetValue(X, Y: Cardinal; const Value: Cardinal);
     1236begin
     1237  FBits^[X + Y * Cardinal(Width)] := Value;
     1238end;
     1239
    5811240
    5821241{ TFloatMap }
     1242
     1243constructor TFloatMap.Create;
     1244begin
     1245  FBits := nil;
     1246  inherited Create;
     1247end;
     1248
     1249destructor TFloatMap.Destroy;
     1250begin
     1251  FreeMem(FBits);
     1252  inherited;
     1253end;
     1254
     1255procedure TFloatMap.Assign(Source: TPersistent);
     1256begin
     1257  BeginUpdate;
     1258  try
     1259    if Source is TFloatMap then
     1260    begin
     1261      inherited SetSize(TFloatMap(Source).Width, TFloatMap(Source).Height);
     1262      Move(TFloatMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(TFloat));
     1263    end
     1264    //else if Source is TBitmap32 then
     1265    //  ReadFrom(TBitmap32(Source), ctWeightedRGB)
     1266    else
     1267      inherited;
     1268  finally
     1269    EndUpdate;
     1270    Changed;
     1271  end;
     1272end;
    5831273
    5841274procedure TFloatMap.ChangeSize(var Width, Height: Integer; NewWidth,
    5851275  NewHeight: Integer);
    5861276begin
    587   SetLength(FBits, NewWidth * NewHeight);
     1277  ReallocMem(FBits, NewWidth * NewHeight * SizeOf(TFloat));
    5881278  Width := NewWidth;
    5891279  Height := NewHeight;
     
    5921282procedure TFloatMap.Clear;
    5931283begin
    594   FillChar(FBits[0], Width * Height * SizeOf(TFloat), 0);
     1284  FillChar(FBits^, Width * Height * SizeOf(TFloat), 0);
    5951285  Changed;
    5961286end;
     
    6011291begin
    6021292  for Index := 0 to Width * Height - 1 do
    603     FBits[Index] := FillValue;
     1293    FBits^[Index] := FillValue;
    6041294  Changed;
    6051295end;
    6061296
    607 destructor TFloatMap.Destroy;
     1297function TFloatMap.Empty: Boolean;
     1298begin
     1299  Result := not Assigned(FBits);
     1300end;
     1301
     1302function TFloatMap.GetScanline(Y: Integer): PFloatArray;
     1303begin
     1304  Result := @FBits^[Y * Width];
     1305end;
     1306
     1307function TFloatMap.GetValPtr(X, Y: Integer): GR32.PFloat;
     1308begin
     1309  Result := @FBits^[X + Y * Width];
     1310end;
     1311
     1312function TFloatMap.GetValue(X, Y: Integer): TFloat;
     1313begin
     1314  Result := FBits^[X + Y * Width];
     1315end;
     1316
     1317procedure TFloatMap.SetValue(X, Y: Integer; const Value: TFloat);
     1318begin
     1319  FBits^[X + Y * Width] := Value;
     1320end;
     1321
     1322
     1323{$IFDEF COMPILER2010}
     1324
     1325{ TGenericMap<T> }
     1326
     1327constructor TGenericMap<T>.Create;
    6081328begin
    6091329  FBits := nil;
     1330  inherited Create;
     1331end;
     1332
     1333destructor TGenericMap<T>.Destroy;
     1334begin
     1335  FreeMem(FBits);
    6101336  inherited;
    6111337end;
    6121338
    613 function TFloatMap.Empty: Boolean;
     1339procedure TGenericMap<T>.Assign(Source: TPersistent);
     1340begin
     1341  BeginUpdate;
     1342  try
     1343(*
     1344    if Source is TFloatMap then
     1345    begin
     1346      inherited SetSize(TFloatMap(Source).Width, TFloatMap(Source).Height);
     1347      Move(TFloatMap(Source).Bits[0], Bits[0], Width * Height * SizeOf(TFloat));
     1348    end
     1349    //else if Source is TBitmap32 then
     1350    //  ReadFrom(TBitmap32(Source), ctWeightedRGB)
     1351    else
     1352      inherited;
     1353*)
     1354  finally
     1355    EndUpdate;
     1356    Changed;
     1357  end;
     1358end;
     1359
     1360procedure TGenericMap<T>.ChangeSize(var Width, Height: Integer; NewWidth,
     1361  NewHeight: Integer);
     1362begin
     1363  ReallocMem(FBits, NewWidth * NewHeight * SizeOf(T));
     1364  Width := NewWidth;
     1365  Height := NewHeight;
     1366end;
     1367
     1368procedure TGenericMap<T>.Clear(FillValue: T);
     1369var
     1370  Index: Integer;
     1371begin
     1372  for Index := 0 to Width * Height - 1 do
     1373    Move(FillValue, PByte(FBits)[Index], SizeOf(T));
     1374  Changed;
     1375end;
     1376
     1377procedure TGenericMap<T>.Clear;
     1378begin
     1379  FillChar(FBits^, Width * Height * SizeOf(T), 0);
     1380  Changed;
     1381end;
     1382
     1383function TGenericMap<T>.Empty: Boolean;
    6141384begin
    6151385  Result := not Assigned(FBits);
    6161386end;
    6171387
    618 function TFloatMap.GetBits: PFloatArray;
    619 begin
    620   Result := @FBits[0];
    621 end;
    622 
    623 function TFloatMap.GetValPtr(X, Y: Integer): PFloat;
    624 begin
    625   Result := @FBits[X + Y * Width];
    626 end;
    627 
    628 function TFloatMap.GetValue(X, Y: Integer): TFloat;
    629 begin
    630   Result := FBits[X + Y * Width];
    631 end;
    632 
    633 procedure TFloatMap.SetValue(X, Y: Integer; const Value: TFloat);
    634 begin
    635   FBits[X + Y * Width] := Value;
    636 end;
     1388function TGenericMap<T>.GetValue(X, Y: Integer): T;
     1389begin
     1390  Move(PByte(FBits)[(X + Y * Width) * SizeOf(T)], Result, SizeOf(T));
     1391end;
     1392
     1393procedure TGenericMap<T>.SetValue(X, Y: Integer; const Value: T);
     1394begin
     1395  Move(Value, PByte(FBits)[(X + Y * Width) * SizeOf(T)], SizeOf(T));
     1396end;
     1397
     1398{$ENDIF}
    6371399
    6381400end.
Note: See TracChangeset for help on using the changeset viewer.