📄 tebitmap.pas
字号:
if FImage <> nil then QImage_destroy(FImage);
FImage := nil;
FBits := nil;
{$ENDIF}
inherited Destroy;
end;
procedure TteBitmap.AssignTo(Dest: TPersistent);
var
Bmp: TBitmap;
procedure CopyToBitmap(Bmp: TBitmap);
begin
Bmp.PixelFormat := pf32Bit;
Bmp.Width := FWidth;
Bmp.Height := FHeight;
Draw(Bmp.Canvas, 0, 0);
end;
begin
if Dest is TPicture then CopyToBitmap(TPicture(Dest).Bitmap)
else if Dest is TBitmap then CopyToBitmap(TBitmap(Dest))
else if Dest is TClipboard then
begin
Bmp := TBitmap.Create;
try
CopyToBitmap(Bmp);
TClipboard(Dest).Assign(Bmp);
finally
Bmp.Free;
end;
end
else inherited;
end;
procedure TteBitmap.Assign(Source: TPersistent);
procedure AssignFromBitmap(SrcBmp: TBitmap);
begin
SetSize(SrcBmp.Width, SrcBmp.Height);
if Empty then Exit;
{$IFNDEF KS_CLX}
BitBlt(FDC, 0, 0, FWidth, FHeight, SrcBmp.Canvas.Handle, 0, 0, SRCCOPY);
{$ELSE}
DrawGraphicToBitmap(SrcBmp, Rect(0, 0, FWidth, FHeight));
{$ENDIF}
SetAlpha($FF);
end;
begin
if Source is TteBitmap then
begin
SetSize((Source as TteBitmap).FWidth, (Source as TteBitmap).FHeight);
if Empty then Exit;
MoveLongwordFunc((Source as TteBitmap).Bits, FBits, FWidth * FHeight);
{ Assign properties }
FName := (Source as TteBitmap).FName;
FTransparent := (Source as TteBitmap).FTransparent;
FAlphaBlend := (Source as TteBitmap).FAlphaBlend;
end
else
if Source is TBitmap then
begin
AssignFromBitmap((Source as TBitmap));
SetAlpha($FF);
end
else
if Source is TGraphic then
begin
SetSize(TGraphic(Source).Width, TGraphic(Source).Height);
if Empty then Exit;
DrawGraphic(TGraphic(Source), Rect(0, 0, FWidth, FHeight));
SetAlpha($FF);
end
else
if Source is TPicture then
begin
with TPicture(Source) do
begin
if TPicture(Source).Graphic is TBitmap then
AssignFromBitmap(TBitmap(TPicture(Source).Graphic))
else
begin
// icons, metafiles etc...
SetSize(TPicture(Source).Graphic.Width, TPicture(Source).Graphic.Height);
if Empty then Exit;
DrawGraphic(TPicture(Source).Graphic, Rect(0, 0, FWidth, FHeight));
SetAlpha($FF);
end;
end;
end
else { inherited }
inherited;
end;
procedure TteBitmap.SetSize(AWidth, AHeight: Integer);
begin
{$IFNDEF KS_CLX}
AWidth := Abs(AWidth);
AHeight := Abs(AHeight);
if (AWidth = 0) or (AHeight = 0) then Exit;
if (AWidth = FWidth) and (AHeight = FHeight) then Exit;
{ Free resource }
if FDC <> 0 then RemoveBitmapFromList(Self);
if FDC <> 0 then DeleteDC(FDC);
FDC := 0;
if FHandle <> 0 then DeleteObject(FHandle);
FHandle := 0;
FBits := nil;
{ Initialization }
with FBitmapInfo.bmiHeader do
begin
biWidth := AWidth;
biHeight := -AHeight;
end;
{ Create new DIB }
FHandle := CreateDIBSection(0, FBitmapInfo, DIB_RGB_COLORS, Pointer(FBits), 0, 0);
if FBits = nil then
raise Exception.Create('Can''t allocate the DIB handle');
FDC := CreateCompatibleDC(0);
if FDC = 0 then
begin
DeleteObject(FHandle);
FHandle := 0;
FBits := nil;
raise Exception.Create('Can''t create compatible DC');
end;
if SelectObject(FDC, FHandle) = 0 then
begin
DeleteDC(FDC);
DeleteObject(FHandle);
FDC := 0;
FHandle := 0;
FBits := nil;
raise Exception.Create('Can''t select an object into DC');
end;
{ Add to BitmapList }
AddBitmapToList(Self);
{$ELSE}
AWidth := Abs(AWidth);
AHeight := Abs(AHeight);
if (AWidth = 0) or (AHeight = 0) then Exit;
if (AWidth = FWidth) and (AHeight = FHeight) then Exit;
{ Free resource }
if FPainter <> nil then QPainter_destroy(FPainter);
FPainter := nil;
if FImage <> nil then QImage_destroy(FImage);
FImage := nil;
FBits := nil;
{ Initialization }
FImage := QImage_create(AWidth, AHeight, 32, 0, QImageEndian_IgnoreEndian);
if FImage = nil then
begin
FPainter := nil;
FImage := nil;
FBits := nil;
raise Exception.Create('Can''t create QImage');
end;
FPainter := QPainter_create;
if FPainter = nil then
begin
FPainter := nil;
FImage := nil;
FBits := nil;
raise Exception.Create('Can''t create QPainter');
end;
FBits := PteColorArray(QImage_bits(FImage));
{$ENDIF}
FWidth := AWidth;
FHeight := AHeight;
end;
function TteBitmap.Empty: boolean;
begin
{$IFNDEF KS_CLX}
Result := FHandle = 0;
{$ELSE}
Result := FImage = nil;
{$ENDIF}
end;
procedure TteBitmap.Clear(Color: TteColor);
begin
FillLongwordFunc(Bits, FWidth * FHeight, Color);
end;
{ I/O Routines }
procedure TteBitmap.LoadFromStream(Stream: TStream);
var
W, H: integer;
begin
FName := ReadString(Stream);
Stream.Read(W, SizeOf(Integer));
Stream.Read(H, SizeOf(Integer));
if (H > 0) then
begin
{ New format since 3.4.4 }
SetSize(W, H);
if (FWidth = W) and (FHeight = H) then
Stream.Read(FBits^, FWidth * FHeight * SizeOf(Longword));
end
else
begin
H := Abs(H);
SetSize(W, H);
if (FWidth = W) and (FHeight = H) then
Stream.Read(FBits^, FWidth * FHeight * SizeOf(Longword));
FlipHorz;
end;
{ Checking }
CheckingAlphaBlend;
if not FAlphaBlend then CheckingTransparent;
end;
procedure TteBitmap.SaveToStream(Stream: TStream);
var
NewFormatHeight: integer;
begin
WriteString(Stream, FName);
Stream.Write(FWidth, SizeOf(Integer));
NewFormatHeight := FHeight; { New format since 3.4.4 }
Stream.Write(NewFormatHeight, SizeOf(Integer));
Stream.Write(FBits^, FWidth * FHeight * SizeOf(Longword));
end;
type
TRGB = packed record
R, G, B: Byte;
end;
TPCXHeader = record
FileID: Byte; // $0A for PCX files, $CD for SCR files
Version: Byte; // 0: version 2.5; 2: 2.8 with palette; 3: 2.8 w/o palette; 5: version 3
Encoding: Byte; // 0: uncompressed; 1: RLE encoded
BitsPerPixel: Byte;
XMin,
YMin,
XMax,
YMax, // coordinates of the corners of the image
HRes, // horizontal resolution in dpi
VRes: Word; // vertical resolution in dpi
ColorMap: array[0..15] of TRGB; // color table
Reserved,
ColorPlanes: Byte; // color planes (at most 4)
BytesPerLine, // number of bytes of one line of one plane
PaletteType: Word; // 1: color or b&w; 2: gray scale
Fill: array[0..57] of Byte;
end;
procedure TteBitmap.LoadFromPcxStream(Stream: TStream);
const
FSourceBPS: byte = 8;
FTargetBPS: byte = 8;
var
Header: TPCXHeader;
Bitmap: TBitmap;
procedure PcxDecode(var Source, Dest: Pointer; PackedSize, UnpackedSize: Integer);
var
Count: Integer;
SourcePtr,
TargetPtr: PByte;
begin
SourcePtr := Source;
TargetPtr := Dest;
while UnpackedSize > 0 do
begin
if (SourcePtr^ and $C0) = $C0 then
begin
// RLE-Code
Count := SourcePtr^ and $3F;
Inc(SourcePtr);
if UnpackedSize < Count then Count := UnpackedSize;
FillChar(TargetPtr^, Count, SourcePtr^);
Inc(SourcePtr);
Inc(TargetPtr, Count);
Dec(UnpackedSize, Count);
end
else
begin
// not compressed
TargetPtr^ := SourcePtr^;
Inc(SourcePtr);
Inc(TargetPtr);
Dec(UnpackedSize);
end;
end;
end;
function PcxCreateColorPalette(Data: array of Pointer; ColorCount: Cardinal): HPALETTE;
var
I, MaxIn, MaxOut: Integer;
LogPalette: TMaxLogPalette;
RunR8: PByte;
begin
FillChar(LogPalette, SizeOf(LogPalette), 0);
LogPalette.palVersion := $300;
if ColorCount > 256 then
LogPalette.palNumEntries := 256
else
LogPalette.palNumEntries := ColorCount;
RunR8 := Data[0];
for I := 0 to LogPalette.palNumEntries - 1 do
begin
LogPalette.palPalEntry[I].peRed := RunR8^;
Inc(RunR8);
LogPalette.palPalEntry[I].peGreen := RunR8^;
Inc(RunR8);
LogPalette.palPalEntry[I].peBlue := RunR8^; Inc(
RunR8);
end;
MaxIn := (1 shl FSourceBPS) - 1;
MaxOut := (1 shl FTargetBPS) - 1;
if (FTargetBPS <= 8) and (MaxIn <> MaxOut) then
begin
MaxIn := (1 shl FSourceBPS) - 1;
MaxOut := (1 shl FTargetBPS) - 1;
if MaxIn < MaxOut then
begin
{ palette is too small, enhance it }
for I := MaxOut downto 0 do
begin
LogPalette.palPalEntry[I].peRed := LogPalette.palPalEntry[MulDiv16(I, MaxIn, MaxOut)].peRed;
LogPalette.palPalEntry[I].peGreen := LogPalette.palPalEntry[MulDiv16(I, MaxIn, MaxOut)].peGreen;
LogPalette.palPalEntry[I].peBlue := LogPalette.palPalEntry[MulDiv16(I, MaxIn, MaxOut)].peBlue;
end;
end
else
begin
{ palette contains too many entries, shorten it }
for I := 0 to MaxOut do
begin
LogPalette.palPalEntry[I].peRed := LogPalette.palPalEntry[MulDiv16(I, MaxIn, MaxOut)].peRed;
LogPalette.palPalEntry[I].peGreen := LogPalette.palPalEntry[MulDiv16(I, MaxIn, MaxOut)].peGreen;
LogPalette.palPalEntry[I].peBlue := LogPalette.palPalEntry[MulDiv16(I, MaxIn, MaxOut)].peBlue;
end;
end;
LogPalette.palNumEntries := MaxOut + 1;
end;
{ finally create palette }
Result := CreatePalette(PLogPalette(@LogPalette)^);
end;
procedure MakePalette;
var
PCXPalette: array[0..255] of TRGB;
OldPos: Integer;
Marker: Byte;
begin
if (Header.Version <> 3) or (Bitmap.PixelFormat = pf1Bit) and
(Bitmap.PixelFormat = pf8Bit) then
begin
OldPos := Stream.Position;
{ 256 colors with 3 components plus one marker byte }
Stream.Position := Stream.Size - 769;
Stream.Read(Marker, 1);
Stream.Read(PCXPalette[0], 768);
Bitmap.Palette := PcxCreateColorPalette([@PCXPalette], 256);
Stream.Position := OldPos;
end
else
Bitmap.Palette := SystemPalette16;
end;
procedure RowConvertIndexed8(Source: array of Pointer; Target: Pointer; Count: Cardinal; Mask: Byte);
var
SourceRun, TargetRun: PByte;
begin
SourceRun := Source[0];
TargetRun := Target;
if (FSourceBPS = FTargetBPS) and (Mask = $FF) then
Move(SourceRun^, TargetRun^, (Count * FSourceBPS + 7) div 8);
end;
var
PCXSize, Size: Cardinal;
RawBuffer, DecodeBuffer: Pointer;
Run: PByte;
I: Integer;
Line: PByte;
Increment: Cardinal;
begin
{ Load from PCX - 8-bit indexed RLE compressed/uncompressed }
{$WARNINGS OFF}
Bitmap := TBitmap.Create;
try
Bitmap.Handle := 0;
Stream.Read(Header, SizeOf(Header));
PCXSize := Stream.Size - Stream.Position;
with Header do
begin
if not (FileID in [$0A, $CD]) then Exit;
Bitmap.PixelFormat := pf8bit;
MakePalette;
Bitmap.Width := XMax - XMin + 1;
Bitmap.Height := YMax - YMin + 1;
{ adjust alignment of line }
Increment := ColorPlanes * BytesPerLine;
{ Decompress }
if Header.Encoding = 1 then
begin
{ RLE }
Size := Increment * Bitmap.Height;
GetMem(DecodeBuffer, Size);
GetMem(RawBuffer, PCXSize);
try
Stream.ReadBuffer(RawBuffer^, PCXSize);
PcxDecode(RawBuffer, DecodeBuffer, PCXSize, Size);
finally
if Assigned(RawBuffer) then FreeMem(RawBuffer);
end;
end
else
begin
GetMem(DecodeBuffer, PCXSize);
Stream.ReadBuffer(DecodeBuffer^, PCXSize);
end;
try
Run := DecodeBuffer;
{ PCX 8 bit Index }
for I := 0 to Bitmap.Height - 1 do
begin
Line := Bitmap.ScanLine[I];
RowConvertIndexed8([Run], Line, Bitmap.Width, $FF);
Inc(Run, Increment);
end;
finally
if Assigned(DecodeBuffer) then FreeMem(DecodeBuffer);
end;
end;
{ Assign to Self }
Assign(Bitmap);
finally
Bitmap.Free;
end;
{$WARNINGS ON}
end;
{ Checking routines }
const
Quantity = 6;
procedure TteBitmap.CheckingAlphaBlend;
var
i: integer;
C: PteColor;
begin
FAlphaBlend := false;
C := @FBits[0];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -