mirror of
https://github.com/doublecmd/doublecmd.git
synced 2026-06-21 09:58:13 +00:00
1048 lines
30 KiB
ObjectPascal
1048 lines
30 KiB
ObjectPascal
Unit uFastBitmap;
|
||
(*==============================================================================
|
||
DESCRIPTION : Classe de manipulation basique de bitmap en 32 bit.
|
||
Basic Class for manipulating 32 bit Bitmap
|
||
DATE : 17/06/2018
|
||
VERSION : 1.0
|
||
AUTEUR : J.Delauney (BeanzMaster)
|
||
LICENCE : MPL
|
||
================================================================================
|
||
*)
|
||
|
||
{$mode objfpc}{$H+}
|
||
{$modeswitch advancedrecords}
|
||
|
||
Interface
|
||
|
||
Uses
|
||
LCLType, LCLIntf, Classes, SysUtils, GraphType, Graphics, Contnrs, Dialogs,
|
||
IntfGraphics, FPimage;
|
||
|
||
Const
|
||
{ Constantes utiles pour le calcul sur les masques de couleur }
|
||
{ Useful constants for calculation on color masks }
|
||
{$IFDEF WINDOWS} // Format BGRA
|
||
cBlueOrder = 0;
|
||
cGreenOrder = 1;
|
||
cRedOrder = 2;
|
||
cAlphaOrder = 3;
|
||
{$ELSE} // Format RGBA
|
||
cRedOrder = 0;
|
||
cGreenOrder = 1;
|
||
cBlueOrder = 2;
|
||
cAlphaOrder = 3;
|
||
{$ENDIF}
|
||
cRedShift = cRedOrder * 8;
|
||
cGreenShift = cGreenOrder * 8;
|
||
cBlueShift = cBlueOrder * 8;
|
||
cAlphaShift = cAlphaOrder * 8;
|
||
|
||
maskRed = 1;
|
||
maskGreen = 2;
|
||
maskBlue = 4;
|
||
maskAlpha = 8;
|
||
maskRGB = maskRed Or maskGreen Or maskBlue;
|
||
maskRGBA = maskRGB Or maskAlpha;
|
||
|
||
Type
|
||
{ TColorRGB24 : Définition d'un pixel sur 24 bits au format RGB }
|
||
{ TColorRGB24 : Definition of a 24-bit pixel in RGB format }
|
||
TColorRGB24Type = packed array[0..2] of byte;
|
||
TColorRGB24 = packed record
|
||
{ Creation de la couleur / Create Color }
|
||
procedure Create(R,G,B : Byte); Overload;
|
||
procedure Create(Color:TColor); Overload;
|
||
|
||
{ Conversion vers un TColor / Convert to TColor }
|
||
function ToColor : TColor;
|
||
|
||
Case Integer of
|
||
0 : (V:TColorRGB24Type); // Acces via Tableau / Array
|
||
1 : (Red, Green, Blue:Byte); // Acces via Composantes / Channel
|
||
end;
|
||
|
||
{ TColor32 : Définition d'un pixel sur 32 bits au format RGBA ou BGRA suivant l'OS }
|
||
{ TColor32: Definition of a 32-bit pixel in RGBA or BGRA format depending on the OS }
|
||
TColor32Type = packed array[0..3] of byte;
|
||
TColor32 = Packed Record
|
||
private
|
||
function getColorComponent(Index : Integer): byte;
|
||
procedure SetColorComponent(Index : Integer; aValue:Byte);
|
||
public
|
||
{ Creation de la couleur / Create Color }
|
||
procedure Create(R,G,B,A : Byte); Overload;
|
||
procedure Create(R,G,B : Byte); Overload;
|
||
procedure Create(Color : TColor); Overload;
|
||
procedure Create(Color : TColorRGB24); Overload;
|
||
|
||
{ Conversion vers un TColor / Convert to TColor }
|
||
function ToColor : TColor;
|
||
{ Conversion vers un TColorRGB24 / Convert to TColorRGB24 }
|
||
function ToColorRGB24 : TColorRGB24;
|
||
{ Conversion vers un TFPColor / Convert to TFPColor }
|
||
function ToFPColor : TFPColor;
|
||
|
||
{ Mixage de la couleur courrante avec la couleur "Color" avec prise en charge du canal Alpha }
|
||
{ Mix current color with 'Color' color with Alpha channel support }
|
||
function Blend(Color : TColor32): TColor32;
|
||
|
||
{ Vérifie si 2 valeurs sont identiques / Check if 2 colors are equal }
|
||
class operator =(Color1,Color2 : TColor32):Boolean;
|
||
|
||
{ Accès aux composantes de la couleur / Color channel access }
|
||
property Red:Byte Index cRedOrder read GetColorComponent Write SetColorComponent;
|
||
property Green:Byte Index cGreenOrder read GetColorComponent Write SetColorComponent;
|
||
property Blue:Byte Index cBlueOrder read GetColorComponent Write SetColorComponent;
|
||
property Alpha:Byte Index cAlphaOrder read GetColorComponent Write SetColorComponent;
|
||
|
||
Case Integer of
|
||
0 : (V:TColor32Type); // Acces via tableau / Array
|
||
1 : (AsInteger : Integer); // Acces via Integer
|
||
End;
|
||
PColor32 = ^TColor32;
|
||
|
||
{ TColor32Item : Objet persistant englobant une couleur de type TColor32 }
|
||
{ TColor32Item: Persistent object that includes a TColor32 color }
|
||
TColor32Item = Class(TPersistent)
|
||
Private
|
||
FColor: TColor32;
|
||
FName: String;
|
||
FTag: Integer;
|
||
|
||
Procedure SetRed(Const AValue: Byte);
|
||
Procedure SetGreen(Const AValue: Byte);
|
||
Procedure SetBlue(Const AValue: Byte);
|
||
Procedure SetAlpha(Const AValue: Byte);
|
||
Procedure SetValue(Const AValue: TColor32);
|
||
Procedure SetColorName(Const aName: String);
|
||
|
||
Function getRed: Byte;
|
||
Function getGreen: Byte;
|
||
Function getBlue: Byte;
|
||
Function getAlpha: Byte;
|
||
Function getValue: TColor32;
|
||
|
||
Protected
|
||
Public
|
||
Constructor Create;
|
||
Destructor Destroy; override;
|
||
|
||
{ Valeur de la couleur / Value of the color }
|
||
Property Value: TColor32 read getValue write setValue;
|
||
{ Nom de la couleur eg : clrRed / Name of the color}
|
||
Property Name: String read FName write setColorName;
|
||
Published
|
||
{ Valeur du canal rouge / Red channel }
|
||
Property Red: Byte read getRed write setRed;
|
||
{ Valeur du canal vert / Green channel }
|
||
Property Green: Byte read getRed write setGreen;
|
||
{ Valeur du canal Bleu / Blue channel }
|
||
Property Blue: Byte read getRed write setBlue;
|
||
{ Valeur du canal alpha pour la transparence / Alpha channel for transparency }
|
||
Property Alpha: Byte read getRed write setAlpha;
|
||
{ Valeur complémentaire personnel / User define value }
|
||
Property Tag: Integer read FTag write FTag;
|
||
End;
|
||
|
||
{ TColor32List : Classe pour la gestion d'une palette (liste) de couleurs }
|
||
{ TColor32List : Class for managing a palette (list) of colors }
|
||
TColor32List = Class(TObjectList)
|
||
Private
|
||
Protected
|
||
Function GetColorItem(index: Integer): TColor32Item;
|
||
Procedure SetColorItem(index: Integer; val: TColor32Item);
|
||
Public
|
||
{ Efface la liste / Clear the list }
|
||
procedure Clear; override;
|
||
{ Ajoute une couleur à la liste / Add a color to the list }
|
||
Function AddColor(Const aColor: TColor32): Integer; Overload;
|
||
{ Ajoute une couleur à la liste /Add a color to the list }
|
||
Function AddColor(Const aName: String; Const aColor: TColor32): Integer; Overload;
|
||
{ Ajoute une couleur à la liste / Add a color to the list}
|
||
Function AddColor(Const aColorItem: TColor32Item): Integer; Overload;
|
||
{ Supprime une couleur de la liste / Delete a color of the list }
|
||
Procedure RemoveColor(Const aName: String);
|
||
{ Recherche une couleur dans la liste / Search color in list }
|
||
Function FindColorByName(Const aName: String; Out Index: Integer):TColor32; Overload;
|
||
{ Recherche une couleur dans la liste / Search color in list }
|
||
Function FindColorByName(Const aName: String): TColor32; Overload;
|
||
|
||
{ Colors : Acceder à la couleur "Index" de la liste / Color access with Index }
|
||
Property Colors[Index: Integer]: TColor32Item read GetColorItem write setColorItem;
|
||
End;
|
||
|
||
Const
|
||
clrTransparent : TColor32 = (v:($00,$00,$00,$00));
|
||
clrBlack : TColor32 = (v:($00,$00,$00,$FF));
|
||
clrWhite : TColor32 = (v:($FF,$FF,$FF,$FF));
|
||
|
||
|
||
Type
|
||
{ TFastBitmapDrawMode : Mode d'Affichage pour la fonction PutImage de TFastBitmap }
|
||
{ TFastBitmapDrawMode : Display Mode for the PutImage Function of TFastBitmap }
|
||
TFastBitmapDrawMode = ( dmSet, dmAlpha, dmAlphaCheck);
|
||
|
||
{ TFastBitmap }
|
||
{ Classe d'aide à la manipulation d'une image }
|
||
{ Help class for image manipulation }
|
||
TFastBitmap = Class
|
||
Strict private
|
||
FTransparentColor : TColor; // Couleur transparent à pour l'affichage via TBitmap de la LCL si besoin / Transparent color for display via TBitmap of the LCL if needed
|
||
|
||
FData : PDWord; // Tampon de stockage des données d'un bitmap / Buffer for storing data from a bitmap
|
||
FWidth : Integer; // Largeur du bitmap / Width
|
||
FHeight : Integer; // Hauteur du Bitmap / Height
|
||
FSize : Int64; // Taille du tampon en octet / Size in byte
|
||
|
||
protected
|
||
|
||
procedure SetWidth(NewWidth : Integer);
|
||
procedure SetHeight(NewHeight : Integer);
|
||
|
||
function BuildBitmap : Graphics.TBitmap;
|
||
function IsClipped(X,Y:Integer) : Boolean;
|
||
|
||
|
||
Public
|
||
Constructor Create; Overload;
|
||
Constructor Create(NewWidth, NewHeight : Integer); Overload;
|
||
Destructor Destroy; Override;
|
||
|
||
{ Assigne les donnée d'un autre TFastBitmap / Assign another TFastBitmap }
|
||
procedure Assign(aFastBitmap : TFastBitmap);
|
||
{ Modifie les dimensions du bitmap / Change size of bitmap }
|
||
procedure SetSize(NewWidth, NewHeight : Integer);
|
||
{ Importation des données d'un TRawImage. Retourne "TRUE" en cas de succès }
|
||
{ Import from RawImage. Return TRUE on success }
|
||
function ImportFromRawImage(Const ARawImage : TRawImage):Boolean;
|
||
{ Importation des données d'un TBitmap. Retourne "TRUE" en cas de succès }
|
||
{ Import from TBitmap. Return TRUE on success }
|
||
function ImportFromBitmap(Const ABitmap :Graphics.TBitmap):Boolean;
|
||
{ Efface le bitmap avec la couleur "Color" / Clear bitmap with Color }
|
||
procedure Clear(Color : TColor32);
|
||
{ Retourne le tampon du bitmap / Return bitmap buffer }
|
||
function GetSurfaceBuffer : PColor32;
|
||
{ Retourne l'adresse de la ligne "Y" dans le tampon / Return address in buffer of a line }
|
||
function GetScanLine(Y : Integer) : PColor32;
|
||
{ Retourne l'adresse du pixel à la position "X,Y" dans le tampon / Return address at X,Y}
|
||
function GetPixelPtr(X, Y : Integer) : PColor32;
|
||
{ Ecrit un pixel de couleur "Color" à la position "X,Y / Put pixel X,Y with Color }
|
||
procedure PutPixel(X,Y:Integer; Color : TColor32);
|
||
{ Lit un pixel de couleur "Color" à la position "X,Y / Get color of pixel at X,Y }
|
||
function GetPixel(X,Y:Integer): TColor32;
|
||
{ Ecrit un pixel de en mixant couleur "Color" avec la couleur du pixel présent dans le tampon à la position "X,Y }
|
||
{ Writes a pixel by mixing 'Color' color with the color of the pixel present in the buffer at the 'X, Y' position }
|
||
procedure PutPixelBlend(X,Y : Integer; Color : TColor32);
|
||
{ Copie une image source "Src" depuis la position "SrcX,SrcY" et de dimension "SrcWidthxSrcHeight" dans le bitmap à la position "DstX, DstY
|
||
et suivant le "Mode"
|
||
Mode : TFastBitmapDrawMode
|
||
- dmSet : Copie brute de l'image
|
||
- dmAlpha : Copie les pixel de l'image source en mixant les couleurs avec celles du bitmap en fonction de leur valeur Alpha
|
||
- dmAlphaCheck : Copie les pixels de l'image source seulement si le pixel est visible (Alpha <> 0)
|
||
Note : les dimensions et les positions entre le bitmap et l'image source sont automatiquement ajustées si besoin.
|
||
|
||
--------------------------
|
||
Copy a source image 'Src' from the position 'SrcX, SrcY' and dimension 'SrcWidthxSrcHeight' into the bitmap at the position 'DstX, DstY
|
||
and following the 'Mode'
|
||
Mode: TFastBitmapDrawMode
|
||
- dmSet: Raw copy of the image
|
||
- dmAlpha: Copy the pixels of the source image by mixing the colors with those of the bitmap according to their Alpha value
|
||
- dmAlphaCheck: Copy the pixels of the source image only if the pixel is invisible (Alpha <> 0)
|
||
Note: The dimensions and positions between the bitmap and the source image are automatically adjusted if necessary.
|
||
}
|
||
procedure PutImage(Src : TFastBitmap; SrcX, SrcY, SrcWidth, SrcHeight, DstX, DstY : Integer; Mode : TFastBitmapDrawMode);
|
||
{ Creation d'un clone du bitmap (nouvelle instance) / Create clone (new instance) }
|
||
function Clone : TFastBitmap;
|
||
{ Retourne un bitmap de type LCL ==> Graphics.TBitmap / Return a TBitmap}
|
||
function GetBitmap : Graphics.TBitmap;
|
||
{ Dessine le bitmap sur un canvas à la position "X,Y" / Draw the bitmap on a canvas }
|
||
procedure Draw(ACanvas : TCanvas; X,Y : Integer); Overload;
|
||
{ Dessine le bitmap sur un canvas délimité par "Rect" / Draw the bitmap on a canvas delimited by "Rect" }
|
||
procedure Draw(ACanvas : TCanvas; Rect : TRect); Overload;
|
||
{ Inverse les composante de couleur Rouge et Bleu du bitmap / Swap Red and Blue channel }
|
||
procedure SwapRB;
|
||
|
||
// procedure HLine(X,Y,X2 : Integer; aColor : TColor32);
|
||
{ Information sur la couleur assignée à la transparence (seulement valable si différent de clrTransparent) / Return the transparency color }
|
||
property TransparentColor : TColor Read FTransparentColor Write FTransparentColor;
|
||
{ Largeur du bitmap / Width }
|
||
property Width : Integer Read FWidth Write SetWidth;
|
||
{ Hauteur du bitmap / Height }
|
||
property Height : Integer Read FHeight Write SetHeight;
|
||
{ Taille du tampon en octet / Size of the buffer }
|
||
property Size : Int64 Read FSize;
|
||
End;
|
||
|
||
Implementation
|
||
|
||
Uses Types, Math, GifViewerStrConsts;
|
||
|
||
|
||
|
||
{%region=====[ TColorRGB24 ]====================================================}
|
||
|
||
Procedure TColorRGB24.Create(R, G, B : Byte);
|
||
Begin
|
||
Red := R;
|
||
Green := G;
|
||
Blue := B;
|
||
End;
|
||
|
||
Procedure TColorRGB24.Create(Color : TColor);
|
||
Var
|
||
lr,lg,lb : Byte;
|
||
Begin
|
||
lr := Color;
|
||
lg := Color shr 8;
|
||
lb := Color shr 16;
|
||
Create(lr,lg,lb);
|
||
End;
|
||
|
||
Function TColorRGB24.ToColor : TColor;
|
||
Begin
|
||
Result := Red + (Green shl 8) + (Blue shl 16);
|
||
End;
|
||
|
||
{%endregion%}
|
||
|
||
{%region=====[ TColor32 ]===================================================}
|
||
|
||
function TColor32.getColorComponent(Index: Integer): byte;
|
||
Begin
|
||
result := v[Index];
|
||
End;
|
||
|
||
procedure TColor32.SetColorComponent(Index: Integer; aValue: Byte);
|
||
Begin
|
||
v[Index] := aValue;
|
||
End;
|
||
|
||
procedure TColor32.Create(R, G, B, A: Byte);
|
||
Begin
|
||
Red := R;
|
||
Green := G;
|
||
Blue := B;
|
||
Alpha := A;
|
||
End;
|
||
|
||
procedure TColor32.Create(R, G, B: Byte);
|
||
Begin
|
||
Create(R,G,B,255);
|
||
End;
|
||
|
||
procedure TColor32.Create(Color: TColor);
|
||
Var
|
||
ColorRGB24 : TColorRGB24;
|
||
Begin
|
||
{%H-}ColorRGB24.Create(Color);
|
||
Create(ColorRGB24);
|
||
End;
|
||
|
||
procedure TColor32.Create(Color: TColorRGB24);
|
||
Begin
|
||
Create(Color.Red,Color.Green,Color.Blue);
|
||
End;
|
||
|
||
function TColor32.ToColor: TColor;
|
||
Begin
|
||
Result := ToColorRGB24.ToColor;
|
||
End;
|
||
|
||
function TColor32.ToColorRGB24: TColorRGB24;
|
||
Begin
|
||
Result.Red := Red;
|
||
Result.Green := Green;
|
||
Result.Blue := Blue;
|
||
End;
|
||
|
||
function TColor32.ToFPColor: TFPColor;
|
||
begin
|
||
Result.Red := Self.Red shl 8 + Self.Red;
|
||
Result.Green := Self.Green shl 8 + Self.Green;
|
||
Result.Blue := Self.Blue shl 8 + Self.Blue;
|
||
Result.Alpha := Self.Alpha shl 8 + Self.Alpha;
|
||
end;
|
||
|
||
function TColor32.Blend(Color: TColor32): TColor32;
|
||
var
|
||
factor, factor2:single;
|
||
begin
|
||
|
||
if Color.Alpha = 255 then Result := Color
|
||
else if (Color.Alpha = 0) or (Self = Color) then Result:= Self
|
||
else
|
||
begin
|
||
factor := Color.Alpha / 255;
|
||
factor2 := 1 - Factor;
|
||
Result.Red := Round((Self.Red*Factor)+(Color.Red*factor2));
|
||
Result.Green := Round((Self.Green*Factor)+(Color.Green*Factor2));
|
||
Result.Blue := Round((Self.Blue*Factor)+(Color.Blue*Factor2));
|
||
Result.alpha := Round((Self.Alpha*Factor)+(Color.Alpha*Factor2));
|
||
End;
|
||
end;
|
||
|
||
class operator TColor32.=(Color1, Color2: TColor32): Boolean;
|
||
Begin
|
||
Result := False;
|
||
if (Color1.Alpha = 0) and (Color2.Alpha = 0) then Result :=True
|
||
else Result := ((Color1.Red = Color2.Red) and (Color1.Green = Color2.Green) and (Color1.Blue = Color2.Blue) and (Color1.Alpha = Color2.Alpha))
|
||
End;
|
||
|
||
{%endregion%}
|
||
|
||
{%region=====[ TColor32Item ]===============================================}
|
||
|
||
Constructor TColor32Item.Create;
|
||
Begin
|
||
Inherited Create;
|
||
FName := 'Black';
|
||
FColor.Create(0,0,0);
|
||
FTag := 0;
|
||
End;
|
||
|
||
Destructor TColor32Item.Destroy;
|
||
Begin
|
||
Inherited Destroy;
|
||
End;
|
||
|
||
Procedure TColor32Item.SetRed(Const AValue: Byte);
|
||
Begin
|
||
If AValue = FColor.red Then exit;
|
||
FColor.Red := AValue;
|
||
End;
|
||
|
||
Procedure TColor32Item.SetGreen(Const AValue: Byte);
|
||
Begin
|
||
If AValue = FColor.Green Then exit;
|
||
FColor.Green := AValue;
|
||
End;
|
||
|
||
Procedure TColor32Item.SetBlue(Const AValue: Byte);
|
||
Begin
|
||
If AValue = FColor.Blue Then exit;
|
||
FColor.Blue := AValue;
|
||
End;
|
||
|
||
Procedure TColor32Item.SetAlpha(Const AValue: Byte);
|
||
Begin
|
||
If AValue = FColor.Alpha Then exit;
|
||
FColor.Alpha := AValue;
|
||
End;
|
||
|
||
Procedure TColor32Item.SetValue(Const AValue: TColor32);
|
||
Begin
|
||
If AValue = FColor Then exit;
|
||
FColor := AValue;
|
||
End;
|
||
|
||
Function TColor32Item.getRed: Byte;
|
||
Begin
|
||
Result := FColor.Red;
|
||
End;
|
||
|
||
Function TColor32Item.getGreen: Byte;
|
||
Begin
|
||
Result := FColor.Green;
|
||
End;
|
||
|
||
Function TColor32Item.getBlue: Byte;
|
||
Begin
|
||
Result := FColor.Blue;
|
||
End;
|
||
|
||
Function TColor32Item.getAlpha: Byte;
|
||
Begin
|
||
Result := FColor.Alpha;
|
||
End;
|
||
|
||
Function TColor32Item.getValue: TColor32;
|
||
Begin
|
||
Result := FColor;
|
||
End;
|
||
|
||
Procedure TColor32Item.SetColorName(Const aName: String);
|
||
Begin
|
||
If FName = aName Then exit;
|
||
FName := aName;
|
||
End;
|
||
|
||
{%endregion%}
|
||
|
||
{%region ====[ TColor32List ]===============================================}
|
||
|
||
Function TColor32List.GetColorItem(index: Integer): TColor32Item;
|
||
Begin
|
||
Result := TColor32Item(Get(Index));
|
||
End;
|
||
|
||
Procedure TColor32List.SetColorItem(index: Integer; val: TColor32Item);
|
||
Begin
|
||
Put(Index, Val);
|
||
End;
|
||
|
||
procedure TColor32List.Clear;
|
||
Var
|
||
anItem: TColor32Item;
|
||
i : Integer;
|
||
Begin
|
||
inherited Clear;
|
||
If Count > 0 then
|
||
begin
|
||
For i :=Count -1 downto 0 do
|
||
begin
|
||
AnItem:= Colors[i];
|
||
if anItem<>nil then anItem.Free;
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
Function TColor32List.AddColor(Const aColor: TColor32): Integer;
|
||
Var
|
||
aColorItem: TColor32Item;
|
||
Begin
|
||
aColorItem := TColor32Item.Create;
|
||
aColorItem.Value := aColor;
|
||
Result := Add(aColorItem);
|
||
End;
|
||
|
||
Function TColor32List.AddColor(Const aName: String; Const aColor: TColor32): Integer;
|
||
Var
|
||
aColorItem: TColor32Item;
|
||
Begin
|
||
aColorItem := TColor32Item.Create;
|
||
aColorItem.Value := aColor;
|
||
aColorItem.Name := aName;
|
||
Result := Add(aColorItem);
|
||
End;
|
||
|
||
Function TColor32List.AddColor(Const aColorItem: TColor32Item): Integer;
|
||
Begin
|
||
Result := Add(aColorItem);
|
||
End;
|
||
|
||
Procedure TColor32List.RemoveColor(Const aName: String);
|
||
Var
|
||
I: Integer;
|
||
Col: TColor32Item;
|
||
Begin
|
||
FindColorByName(aName, I);
|
||
If I > -1 Then
|
||
Begin
|
||
Col := GetColorItem(I);
|
||
If Assigned(Col) Then
|
||
Col.Free;
|
||
Delete(I);
|
||
End;
|
||
End;
|
||
|
||
Function TColor32List.FindColorByName(Const aName: String; Out Index: Integer): TColor32;
|
||
Var
|
||
i: Integer;
|
||
Begin
|
||
Result := clrTransparent;
|
||
Index := -1;
|
||
For i := 0 To Count - 1 Do
|
||
If TColor32Item(Items[i]).Name = aName Then
|
||
Begin
|
||
Index := I;
|
||
Result := TColor32Item(Items[i]).Value;
|
||
break;
|
||
End;
|
||
End;
|
||
|
||
Function TColor32List.FindColorByName(Const aName: String): TColor32;
|
||
Var
|
||
i: Integer;
|
||
Begin
|
||
Result := FindColorByName(aName, I);
|
||
End;
|
||
|
||
{%endregion%}
|
||
|
||
{%region=====[ TFastBitmap ]====================================================}
|
||
|
||
Constructor TFastBitmap.Create(NewWidth, NewHeight : Integer);
|
||
Begin
|
||
inherited Create;
|
||
FWidth := Max(1,NewWidth);
|
||
FHeight := Max(1,NewHeight);
|
||
FData := Nil;
|
||
FSize := (int64(FWidth) * int64(FHeight))*4;
|
||
ReAllocMem(FData,FSize);
|
||
FTransparentColor := clBlack;
|
||
End;
|
||
|
||
Constructor TFastBitmap.Create;
|
||
Begin
|
||
Create(1,1);
|
||
End;
|
||
|
||
Destructor TFastBitmap.Destroy;
|
||
Begin
|
||
FreeMem(FData);
|
||
FData := Nil;
|
||
inherited Destroy;
|
||
End;
|
||
|
||
Procedure TFastBitmap.SetWidth(NewWidth : Integer);
|
||
Begin
|
||
if NewWidth = FWidth then Exit;
|
||
SetSize(NewWidth, FHeight);
|
||
End;
|
||
|
||
Procedure TFastBitmap.SetHeight(NewHeight : Integer);
|
||
Begin
|
||
if NewHeight = FHeight then Exit;
|
||
SetSize(FWidth, NewHeight);
|
||
End;
|
||
|
||
Function TFastBitmap.BuildBitmap: Graphics.TBitmap;
|
||
Var
|
||
Temp : Graphics.TBitmap;
|
||
IntfBmp : TLazIntfImage;
|
||
ImgFormatDescription: TRawImageDescription;
|
||
W,H,X,Y : Integer;
|
||
SrcPix : PColor32;
|
||
Begin
|
||
|
||
(* /!\ Le code si dessous fonctionne parfaitement sous Windows et Mac.
|
||
Mais sous Linux ce code produit des erreur au niveau de la transparence
|
||
|
||
BmpHandle := 0;
|
||
MskHandle := 0;
|
||
W := FWidth;
|
||
H := FHeight;
|
||
Buffer := PByte(GetSurfaceBuffer);
|
||
|
||
RawImage.Init;
|
||
{$IFDEF WINDOWS}
|
||
RawImage.Description.Init_BPP32_B8G8R8A8_BIO_TTB(W,H);
|
||
{$ELSE}
|
||
RawImage.Description.Init_BPP32_R8G8B8A8_BIO_TTB(W,H);
|
||
{$ENDIF}
|
||
|
||
RawImage.Data := Buffer;
|
||
RawImage.DataSize := FSize;
|
||
|
||
if not RawImage_CreateBitmaps(RawImage, BmpHandle, MskHandle,False) then
|
||
Raise Exception.Create('Impossible de créer le TBitmap')
|
||
else
|
||
begin
|
||
Temp := Graphics.TBitmap.Create;
|
||
Temp.Width := W;
|
||
Temp.Height := H;
|
||
Temp.PixelFormat := pf32bit;
|
||
Temp.Handle := BmpHandle;
|
||
Temp.MaskHandle := MskHandle;
|
||
Temp.Transparent := True;
|
||
//Temp.TransparentColor := FTransparentColor;
|
||
//temp.TransparentMode := tmAuto;
|
||
Result := Temp;
|
||
End;
|
||
*)
|
||
|
||
Result := nil;
|
||
|
||
W := FWidth;
|
||
H := FHeight;
|
||
|
||
// Pour que la transparence soit gérée correctement sous Linux on est obligé de passer par TLazIntfImage
|
||
IntfBmp := TLazIntfImage.Create(W,H);
|
||
ImgFormatDescription.Init_BPP32_B8G8R8A8_BIO_TTB(W, H);
|
||
IntfBmp.DataDescription := ImgFormatDescription;
|
||
|
||
SrcPix := Self.GetSurfaceBuffer;
|
||
For Y:=0 to H-1 do
|
||
For X:=0 to W-1 do
|
||
begin
|
||
IntfBmp.Colors[x, y]:=SrcPix^.ToFPColor;
|
||
inc(SrcPix);
|
||
end;
|
||
|
||
begin
|
||
Temp := Graphics.TBitmap.Create;
|
||
Temp.LoadFromIntfImage(IntfBmp);
|
||
Result := Temp;
|
||
IntfBmp.Free;
|
||
End;
|
||
if Result = nil then
|
||
Raise Exception.Create(rsBitmapCreateError);
|
||
End;
|
||
|
||
Function TFastBitmap.IsClipped(X, Y : Integer) : Boolean;
|
||
Begin
|
||
Result := ((X>=0) and (Y>=0) and (X<FWidth) and (Y<FHeight));
|
||
End;
|
||
|
||
Procedure TFastBitmap.SwapRB;
|
||
var
|
||
Pixptr: PColor32;
|
||
AIntColor : Cardinal;
|
||
PixelCount : Integer;
|
||
begin
|
||
PixPtr := GetSurfaceBuffer;
|
||
PixelCount := (FWidth * FHeight)-1;
|
||
while pixelCount > 0 do
|
||
begin
|
||
AIntColor := PixPtr^.AsInteger;
|
||
PixPtr^.AsInteger := AIntColor and $FF00FF00 or (AintColor and $000000FF SHL 16) or (AIntColor and $00FF0000 SHR 16);
|
||
Inc(PixPtr);
|
||
Dec(pixelCount);
|
||
end;
|
||
end;
|
||
|
||
Procedure TFastBitmap.Assign(aFastBitmap : TFastBitmap);
|
||
Begin
|
||
SetSize(aFastBitMap.Width, aFastBitmap.Height);
|
||
Move(PByte(aFastBitmap.GetSurfaceBuffer)^, PByte(FData)^, FSize);
|
||
End;
|
||
|
||
Procedure TFastBitmap.SetSize(NewWidth, NewHeight : Integer);
|
||
Begin
|
||
FWidth := Max(1,NewWidth);
|
||
FHeight := Max(1,NewHeight);
|
||
FSize :=(int64(FWidth) * int64(FHeight))*4;
|
||
if (FData<>nil) then
|
||
begin
|
||
FreeMem(FData);
|
||
FData := Nil;
|
||
End;
|
||
ReAllocMem(FData,FSize);
|
||
Clear(clrTransparent);
|
||
End;
|
||
|
||
Function TFastBitmap.ImportFromRawImage(Const ARawImage: TRawImage): Boolean;
|
||
var
|
||
BufferData : PByte;
|
||
begin
|
||
SetSize(ARawImage.Description.Width,ARawImage.Description.Height);
|
||
result:=false;
|
||
// On verifie si la taille des deux tampons sont identique
|
||
// Si ce n'est pas le cas, cela veut dire que le TRawImage n'est pas au format 32bit
|
||
if (ARawImage.DataSize= FSize) then
|
||
begin
|
||
try
|
||
BufferData := PByte(Self.getSurfaceBuffer);
|
||
Move(ARawImage.Data^, BufferData^, self.Size);
|
||
{$IFDEF WINDOWS}
|
||
if (ARawImage.Description.RedShift = 0) and ((ARawImage.Description.BlueShift = 16)) then Self.SwapRB; // Le RawImage est-il en RGB, si oui on échange
|
||
{$ELSE}
|
||
if (ARawImage.Description.RedShift = 16) and ((ARawImage.Description.BlueShift = 0)) then Self.SwapRB; // Le RawImage est-il en BGR, si oui on échange
|
||
{$ENDIF}
|
||
finally
|
||
result:=true;
|
||
end;
|
||
end;
|
||
End;
|
||
|
||
Function TFastBitmap.ImportFromBitmap(Const ABitmap: Graphics.TBitmap): Boolean;
|
||
var
|
||
LTempBitmap: Graphics.TBitmap;
|
||
ok,ResetAlpha:Boolean;
|
||
|
||
procedure SetAlpha(Value : Byte);
|
||
var
|
||
i : Integer;
|
||
PixPtr : PColor32;
|
||
maxi : Integer;
|
||
begin
|
||
i:=0;
|
||
Maxi := (FWidth * FHeight)-1;
|
||
PixPtr :=PColor32(FData);// Self.GetScanLine(0);
|
||
While i<Maxi do
|
||
begin
|
||
PixPtr^.Alpha:= Value;
|
||
inc(PixPtr);
|
||
inc(i);
|
||
end;
|
||
end;
|
||
|
||
begin
|
||
ResetAlpha:=False;
|
||
result:=false;
|
||
if (ABitmap.PixelFormat <> pf32bit) then
|
||
begin
|
||
LTempBitmap := Graphics.TBitmap.Create;
|
||
try
|
||
ResetAlpha:=True;
|
||
LTempBitmap.SetSize(ABitmap.Width, ABitmap.Height);
|
||
LTempBitmap.PixelFormat := pf32bit;
|
||
LTempBitmap.Canvas.Draw(0, 0, ABitmap);
|
||
finally
|
||
ok:=Self.ImportFromRawImage(LTempBitmap.RawImage);
|
||
if ResetAlpha then SetAlpha(255);
|
||
FreeAndNil(LTempBitmap);
|
||
result:=true and (ok);
|
||
end;
|
||
end
|
||
else
|
||
begin
|
||
ok:=Self.ImportFromRawImage(ABitmap.RawImage);
|
||
result:=true and (ok);
|
||
end;
|
||
End;
|
||
|
||
Procedure TFastBitmap.Clear(Color : TColor32);
|
||
Begin
|
||
FillDWord(FData^,FWidth * FHeight, DWord(Color));
|
||
End;
|
||
|
||
Function TFastBitmap.GetSurfaceBuffer: PColor32;
|
||
Begin
|
||
Result := PColor32(FData);
|
||
End;
|
||
|
||
Function TFastBitmap.GetScanLine(Y : Integer) : PColor32;
|
||
Var
|
||
yy : DWord;
|
||
Begin
|
||
If (Y<0) or (Y>=FHeight) then
|
||
Raise Exception.Create(rsBitmapScanlineOutOfRange)
|
||
else
|
||
begin
|
||
yy := DWord(FWidth) * DWord(Y);
|
||
Result := PColor32(FData + YY);
|
||
End;
|
||
End;
|
||
|
||
Function TFastBitmap.GetPixelPtr(X, Y : Integer) : PColor32;
|
||
Begin
|
||
Result := nil;
|
||
if IsClipped(X,Y) then
|
||
Begin
|
||
Result := PColor32(FData + (FWidth * Y) + X);
|
||
End;
|
||
End;
|
||
|
||
Procedure TFastBitmap.PutPixel(X, Y : Integer; Color : TColor32);
|
||
Var
|
||
PixelPtr : PColor32;
|
||
Begin
|
||
if IsClipped(X,Y) then
|
||
Begin
|
||
PixelPtr := PColor32(FData + DWord(FWidth * Y));
|
||
Inc(PixelPtr,X);
|
||
PixelPtr^:= Color;
|
||
End;
|
||
End;
|
||
|
||
Function TFastBitmap.GetPixel(X, Y : Integer) : TColor32;
|
||
Var
|
||
PixelPtr : PColor32;
|
||
Begin
|
||
Result := clrTransparent;
|
||
if IsClipped(X,Y) then
|
||
Begin
|
||
PixelPtr := PColor32(FData + (FWidth * Y) + X);
|
||
Result := PixelPtr^;
|
||
End;
|
||
End;
|
||
|
||
Procedure TFastBitmap.PutPixelBlend(X, Y : Integer; Color : TColor32);
|
||
Var
|
||
PixelPtr : PColor32;
|
||
Begin
|
||
if IsClipped(X,Y) then
|
||
Begin
|
||
PixelPtr := PColor32(FData + (FWidth * Y) + X);
|
||
PixelPtr^:= PixelPtr^.Blend(Color);
|
||
End;
|
||
End;
|
||
|
||
Procedure TFastBitmap.PutImage(Src : TFastBitmap; SrcX, SrcY, SrcWidth, SrcHeight, DstX, DstY : Integer; Mode : TFastBitmapDrawMode);
|
||
Var
|
||
SrcPtr, DstPtr : PColor32;
|
||
NextSrcLine, NextDstLine : Integer;
|
||
DstCol, SrcCol : TColor32;
|
||
LineSize,TotalSize,xx,yy,i : Integer;
|
||
|
||
Procedure ClipCopyRect(Var SrcX, SrcY, rWidth, rHeight, DstX, DstY: Integer; SrcImageWidth, SrcImageHeight: Integer; Const DstClip: Types.TRect);
|
||
Var
|
||
diff, OldDstPosX, OldDstPosY: Integer;
|
||
Begin
|
||
OldDstPosX := 0;
|
||
If (DstX < 0) Then OldDstPosX := DstX;
|
||
OldDstPosY := 0;
|
||
If (DstY < 0) Then OldDstPosY := DstY;
|
||
|
||
If DstX < DstClip.Left Then
|
||
Begin
|
||
Diff := DstClip.Left - DstX;
|
||
rWidth := rWidth - Diff;
|
||
SrcX := SrcX + Diff;
|
||
DstX := DstClip.Left;
|
||
End;
|
||
|
||
If DstY < DstClip.Top Then
|
||
Begin
|
||
Diff := DstClip.Top - DstY;
|
||
rHeight := rHeight - Diff;
|
||
SrcY := SrcY + Diff;
|
||
DstY := DstClip.Bottom;
|
||
End;
|
||
|
||
If SrcX < 0 Then
|
||
Begin
|
||
Width := Width + SrcX - OldDstPosX;
|
||
DstX := DstX - SrcX + OldDstPosX;
|
||
SrcX := 0;
|
||
End;
|
||
If SrcY < 0 Then
|
||
Begin
|
||
rHeight := rHeight + SrcX - OldDstPosY;
|
||
DstY := DstY - SrcY + OldDstPosY;
|
||
SrcY := 0;
|
||
End;
|
||
|
||
If ((SrcX + rWidth) > SrcImageWidth) Then rWidth := SrcImageWidth - SrcX;
|
||
If ((SrcY + rHeight) > SrcImageHeight) Then rHeight := SrcImageHeight - SrcY;
|
||
|
||
if DstX > FWidth then DstX := 0;
|
||
if DstY > FHeight then DstY := 0;
|
||
|
||
If ((DstX + rWidth) > (DstClip.Right+1)) Then rWidth := DstClip.Right - DstX;
|
||
If ((DstY + rHeight) > (DstClip.Bottom+1)) Then rHeight := DstClip.Bottom - DstY;
|
||
|
||
End;
|
||
Begin
|
||
|
||
if (SrcWidth = 0) and (SrcHeight = 0) then exit;
|
||
ClipCopyRect(SrcX, SrcY, SrcWidth,SrcHeight, DstX, DstY, Src.Width, Src.Height, Types.Rect(0,0,FWidth-1, FHeight-1));
|
||
|
||
|
||
if (SrcWidth = 1) and (SrcHeight = 1) then
|
||
begin
|
||
Case Mode of
|
||
dmSet :
|
||
begin
|
||
SrcCol := Src.GetPixel(0,0);
|
||
PutPixel(0,0,SrcCol);
|
||
End;
|
||
dmAlpha :
|
||
begin
|
||
SrcCol := Src.GetPixel(0,0);
|
||
DstCol := GetPixel(0,0);
|
||
PutPixel(0,0,DstCol.Blend(SrcCol));
|
||
End;
|
||
dmAlphaCheck :
|
||
begin
|
||
If SrcCol.Alpha > 0 Then
|
||
begin
|
||
SrcCol := Src.GetPixel(0,0);
|
||
DstCol := GetPixel(0,0);
|
||
PutPixel(0,0,DstCol.Blend(SrcCol));
|
||
End
|
||
Else
|
||
begin
|
||
DstCol := GetPixel(0,0);
|
||
PutPixel(0,0,DstCol);
|
||
End;
|
||
End;
|
||
End;
|
||
exit;
|
||
End;
|
||
|
||
SrcPtr := Src.GetPixelPtr(SrcX,SrcY);
|
||
DstPtr := GetPixelPtr(DstX, DstY);
|
||
|
||
if SrcWidth <= Src.Width then
|
||
nextSrcLine := Src.Width
|
||
else
|
||
nextSrcLine := SrcX + (Src.Width - (SrcX + SrcWidth));
|
||
if Mode = dmSet then
|
||
begin
|
||
if (((Src.Width = FWidth) and (Src.Height = FHeight)) and ((SrcWidth = FWidth) and (SrcHeight = FHeight))) then
|
||
Move(SrcPtr^,DstPtr^,DWord(Src.Size))
|
||
else
|
||
begin
|
||
LineSize := SrcWidth * 4;
|
||
For I := 0 to SrcHeight-1 do
|
||
begin
|
||
Move(SrcPtr^, DstPtr^, LineSize);
|
||
Inc(SrcPtr, NextSrcLine);
|
||
Inc(DstPtr, FWidth);
|
||
End;
|
||
End;
|
||
End
|
||
else
|
||
begin
|
||
totalsize := (Src.Width * Src.Height) - 1;
|
||
Dec(SrcHeight);
|
||
xx := 0;
|
||
Dec(SrcWidth);
|
||
nextSrcLine := SrcX + (Src.Width - (SrcX + SrcWidth));
|
||
nextDstLine := DstX + (FWidth - (DstX + SrcWidth));
|
||
yy := 0;
|
||
xx := 0;
|
||
SrcCol := clrTransparent;
|
||
DstCol := clrTransparent;
|
||
While (yy <= TotalSize) Do
|
||
Begin
|
||
DstCol := DstPtr^;
|
||
SrcCol := SrcPtr^;
|
||
Case Mode of
|
||
dmAlpha :
|
||
begin
|
||
DstPtr^ := DstCol.Blend(SrcCol);
|
||
End;
|
||
dmAlphaCheck :
|
||
begin
|
||
If SrcCol.Alpha > 0 Then
|
||
DstPtr^ := DstCol.Blend(SrcCol)
|
||
Else
|
||
DstPtr^ := DstCol;
|
||
End;
|
||
End;
|
||
Inc(xx);
|
||
Inc(yy);
|
||
If (xx > SrcWidth) Then
|
||
Begin
|
||
xx := 0;
|
||
Inc(DstPtr, NextDstLine);
|
||
Inc(SrcPtr, NextSrcLine);
|
||
End
|
||
Else
|
||
Begin
|
||
Inc(SrcPtr);
|
||
Inc(DstPtr);
|
||
End;
|
||
End;
|
||
End;
|
||
End;
|
||
|
||
Function TFastBitmap.Clone : TFastBitmap;
|
||
Var
|
||
NewBmp : TFastBitmap;
|
||
Begin
|
||
NewBmp := TFastBitmap.Create;
|
||
NewBmp.Assign(Self);
|
||
Result := NewBmp;
|
||
End;
|
||
|
||
Function TFastBitmap.GetBitmap : Graphics.TBitmap;
|
||
Begin
|
||
Result := BuildBitmap;
|
||
End;
|
||
|
||
Procedure TFastBitmap.Draw(ACanvas : TCanvas; X, Y : Integer);
|
||
Var
|
||
Tmp : Graphics.TBitmap;
|
||
Begin
|
||
Tmp := BuildBitmap;
|
||
ACanvas.Draw(X,Y,Tmp);
|
||
FreeAndNil(Tmp);
|
||
End;
|
||
|
||
Procedure TFastBitmap.Draw(ACanvas : TCanvas; Rect : TRect);
|
||
Var
|
||
Tmp : Graphics.TBitmap;
|
||
Begin
|
||
Tmp := BuildBitmap;
|
||
ACanvas.StretchDraw(Rect, Tmp);
|
||
FreeAndNil(Tmp);
|
||
End;
|
||
|
||
{%endregion%}
|
||
End.
|
||
|
||
|