📄 tebmpmsk.pas
字号:
unit teBmpMsk;
interface
{$RANGECHECKS OFF}
{$INCLUDE teDefs.inc}
uses
SysUtils, Classes, TransEff, teTimed, Windows, Messages, Graphics, teBkgrnd;
type
TBmpMaskTransition = class(TTimedTransitionEffect)
private
FMask: TBitmap;
FMaskMode: TFCPictureMode;
FSmoothingLevel: Word;
procedure SetMask(Value: TBitmap);
procedure SetSmoothingLevel(const Value: Word);
procedure ExecuteSmooth(Data: TTETransitionData; CurrentFrame, Step,
LastExecutedFrame: Integer);
procedure ExecuteStd(Data: TTETransitionData; CurrentFrame, Step,
LastExecutedFrame: Integer);
procedure SetMaskMode(const Value: TFCPictureMode);
protected
function GetPixelFormat(Device: TTETransitionDevice): TPixelFormat; override;
function GetBitmapsWidth(Data: TTETransitionData): Integer; override;
function Smooth(Device: TTETransitionDevice): Boolean;
procedure Initialize(Data: TTETransitionData; var TotalFrames: Longint);
override;
procedure ExecuteFrame(Data: TTETransitionData; CurrentFrame, Step,
LastExecutedFrame: Longint); override;
function GetInfo(Device: TTETransitionDevice): TTETransitionInfo; override;
public
constructor Create(AOwner: TComponent = nil); override;
destructor Destroy; override;
class function MaskModeAllowed(Mode: TFCPictureMode): Boolean;
class function Description: String; override;
class function GetEditor: String; override;
function GetDelegate(Device: TTETransitionDevice;
const ReturnCopy: Boolean): TTransitionEffect; override;
procedure Assign(Source: TPersistent); override;
function MaxSmoothingLevel: Integer;
published
property Mask: TBitmap read FMask write SetMask;
property MaskMode: TFCPictureMode read FMaskMode write SetMaskMode default fcpmStretch;
property Pass2Options;
property PassSetting;
property Reversed;
property SmoothingLevel: Word read FSmoothingLevel write SetSmoothingLevel default 0;
end;
implementation
uses teRender, teMskWk;
resourcestring
rsTEMaskNot8bit = 'Transition mask should have 8 bits per pixel';
type
TBmpMaskData = class(TTECustomData)
public
Apply256BmpMaskSSubProc,
Apply256BmpMaskSAddProc: PByteArray;
IsSmooth: Boolean;
MaskBmp: TBitmap;
destructor Destroy; override;
end;
var
LevelsArray: array[1..5] of Integer = (8, 16, 32, 64, 128);
{ TBmpMaskTransition }
constructor TBmpMaskTransition.Create(AOwner: TComponent);
begin
inherited;
FMask := TBitmap.Create;
FSmoothingLevel := 0;
FMaskMode := fcpmStretch;
end;
destructor TBmpMaskTransition.Destroy;
begin
FMask.Free;
inherited;
end;
class function TBmpMaskTransition.Description: String;
begin
Result := 'Bitmap mask';
end;
class function TBmpMaskTransition.GetEditor: String;
begin
Result := 'TBmpMaskTransitionEditor';
end;
procedure TBmpMaskTransition.SetMask(Value: TBitmap);
begin
if(Value <> nil) and (not Value.Empty) and (Value.PixelFormat <> pf8bit) then
raise ETransitionEffectError.Create(rsTEMaskNot8bit);
FMask.Assign(Value);
end;
procedure TBmpMaskTransition.Assign(Source: TPersistent);
begin
if Source is TBmpMaskTransition
then
begin
inherited;
Mask.Assign((TBmpMaskTransition(Source).Mask));
MaskMode := TBmpMaskTransition(Source).MaskMode;
SmoothingLevel := TBmpMaskTransition(Source).SmoothingLevel;
end
else inherited;
end;
function TBmpMaskTransition.GetPixelFormat(
Device: TTETransitionDevice): TPixelFormat;
begin
Result := Device.PixelFormat;
if Smooth(Device) and (Result <> pf32bit) then
Result := pf32bit;
end;
function TBmpMaskTransition.GetBitmapsWidth(
Data: TTETransitionData): Integer;
begin
if Smooth(Data.Device)
then Result := (((Data.Width-1) div 8) + 1) * 8
else
begin
if Data.PixelFormat <> pf4bit
then Result := (((Data.Width-1) div 4) + 1) * 4
else Result := (((Data.Width-1) div 8) + 1) * 8;
end;
end;
procedure TBmpMaskTransition.SetSmoothingLevel(const Value: Word);
begin
if Value <= MaxSmoothingLevel then
FSmoothingLevel := Value;
end;
function TBmpMaskTransition.Smooth(Device: TTETransitionDevice): Boolean;
begin
Result :=
TEProcessorInfo.MMX and
(SmoothingLevel > 0) and
(Device.PixelFormat in [pf15bit, pf16bit, pf24bit, pf32bit]);
end;
procedure TBmpMaskTransition.Initialize(Data: TTETransitionData; var
TotalFrames: Longint);
var
BmpMaskData: TBmpMaskData;
begin
inherited;
if Mask.PixelFormat <> pf8bit then
raise ETransitionEffectError.Create(rsTEMaskNot8bit);
TotalFrames := 254;
BmpMaskData := TBmpMaskData.Create(Data);
Data.Custom := BmpMaskData;
BmpMaskData.Apply256BmpMaskSSubProc := nil;
BmpMaskData.Apply256BmpMaskSAddProc := nil;
BmpMaskData.IsSmooth := Smooth(Data.Device);
if BmpMaskData.IsSmooth then
begin
Inc(TotalFrames, LevelsArray[SmoothingLevel]-1);
BmpMaskData.Apply256BmpMaskSSubProc := GetApply256BmpMaskSProc(
LevelsArray[SmoothingLevel], False);
BmpMaskData.Apply256BmpMaskSAddProc := GetApply256BmpMaskSProc(
LevelsArray[SmoothingLevel], True);
end;
BmpMaskData.MaskBmp := TBitmap.Create;
BmpMaskData.MaskBmp.Canvas.Lock;
AdjustBmpForTransition(BmpMaskData.MaskBmp, CopyPalette(Mask.Palette),
Data.Bitmap.Width, Data.Height, pf8bit);
SetStretchBltMode(Data.Canvas.Handle, COLORONCOLOR);
if Reversed then
BmpMaskData.MaskBmp.Canvas.CopyMode := cmNotSrcCopy;
Mask.Canvas.Lock;
try
DrawPicture(Mask, FMaskMode, clNone, nil, BmpMaskData.MaskBmp,
Rect(0, 0, Data.Width, Data.Height), 0, nil);
finally
Mask.Canvas.Unlock;
end;
if Reversed then
BmpMaskData.MaskBmp.Canvas.CopyMode := cmSrcCopy;
end;
procedure TBmpMaskTransition.ExecuteFrame(Data: TTETransitionData;
CurrentFrame, Step, LastExecutedFrame: Longint);
begin
if not TBmpMaskData(Data.Custom).IsSmooth
then ExecuteStd (Data, CurrentFrame, Step, LastExecutedFrame)
else ExecuteSmooth(Data, CurrentFrame, Step, LastExecutedFrame);
end;
procedure TBmpMaskTransition.ExecuteStd(Data: TTETransitionData; CurrentFrame,
Step, LastExecutedFrame: Integer);
var
Work,
Dst,
MaskP: Pointer;
ScanLineSize,
MaskScanLineSize: Longint;
begin
Data.UpdateRect := Rect(0, 0, Data.Width, Data.Height);
Data.UnUpdateRect := Rect(0, 0, 0, 0);
MaskScanLineSize := GetBytesPerScanline(TBmpMaskData(Data.Custom).MaskBmp, pf8bit, 32);
ScanLineSize := GetBytesPerScanline(Data.Bitmap, Data.PixelFormat, 32);
Work := PChar(Data.Bitmap.ScanLine[0]) + ScanlineSize;
Dst := PChar(Data.DstBmp.ScanLine[0]) + ScanlineSize;
MaskP := PChar(TBmpMaskData(Data.Custom).MaskBmp.ScanLine[0]) + MaskScanLineSize;
Apply256Mask(Work, Dst, MaskP, MaskScanLineSize * Data.Height,
255 - CurrentFrame, 255 - LastExecutedFrame, Data.PixelFormat);
end;
procedure TBmpMaskTransition.ExecuteSmooth(Data: TTETransitionData;
CurrentFrame, Step, LastExecutedFrame: Integer);
var
Work,
Dst,
Src,
MaskP: Pointer;
ScanLineSize,
MaskScanLineSize,
Dif: Longint;
BmpMaskData: TBmpMaskData;
begin
BmpMaskData := TBmpMaskData(Data.Custom);
Data.UpdateRect := Rect(0, 0, Data.Width, Data.Height);
Data.UnUpdateRect := Rect(0, 0, 0, 0);
MaskScanLineSize := GetBytesPerScanline(BmpMaskData.MaskBmp, pf8bit, 32);
ScanLineSize := GetBytesPerScanline(Data.Bitmap, Data.PixelFormat, 32);
Work := PChar(Data.Bitmap.ScanLine[0]) + ScanlineSize;
Dst := PChar(Data.DstBmp.ScanLine[0]) + ScanlineSize;
Src := PChar(Data.SrcBmp.ScanLine[0]) + ScanlineSize;
MaskP := PChar(BmpMaskData.MaskBmp.ScanLine[0]) + MaskScanLineSize;
Dif := 255 - CurrentFrame;
Apply256BmpMaskS(TApply256BmpMaskSProc(TBmpMaskData(Data.Custom).Apply256BmpMaskSSubProc),
TApply256BmpMaskSProc(BmpMaskData.Apply256BmpMaskSAddProc), Work, Dst, Src,
MaskP, ScanLineSize, MaskScanLineSize, BmpMaskData.MaskBmp.Width,
Dif, Data.UpdateRect, Data.UnUpdateRect);
end;
function TBmpMaskTransition.GetInfo(Device: TTETransitionDevice):
TTETransitionInfo;
begin
Result := inherited GetInfo(Device) +
[
tetiMillisecondsCapable,
tetiNeedOffScreenBmp,
tetiOffScreenBmpCapable,
tetiStaticSrcPixels,
tetiThreadSafe
];
end;
function TBmpMaskTransition.MaxSmoothingLevel: Integer;
begin
Result := 5;
end;
procedure TBmpMaskTransition.SetMaskMode(const Value: TFCPictureMode);
begin
if(Value <> FMaskMode) and MaskModeAllowed(Value) then
FMaskMode := Value;
end;
class function TBmpMaskTransition.MaskModeAllowed(
Mode: TFCPictureMode): Boolean;
begin
Result := Mode in [fcpmStretch, fcpmTile, fcpmZoom];
end;
function TBmpMaskTransition.GetDelegate(Device: TTETransitionDevice;
const ReturnCopy: Boolean): TTransitionEffect;
begin
if not Mask.Empty
then Result := inherited GetDelegate(Device, ReturnCopy)
else
begin
Result := TFlickerFreeTransition.Create(nil);
Result.Assign(Self);
end;
end;
{ TBmpMaskData }
destructor TBmpMaskData.Destroy;
begin
if Assigned(Apply256BmpMaskSSubProc) then
VirtualFree(Apply256BmpMaskSSubProc, 0, MEM_RELEASE);
if Assigned(Apply256BmpMaskSAddProc) then
VirtualFree(Apply256BmpMaskSAddProc, 0, MEM_RELEASE);
MaskBmp.Canvas.Unlock;
MaskBmp.Free;
inherited;
end;
initialization
TERegisterTransition(TBmpMaskTransition);
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -