mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-04-05 19:58:02 +02:00
209 lines
5.3 KiB
PHP
209 lines
5.3 KiB
PHP
{%MainUnit ../graphics.pp}
|
|
|
|
{******************************************************************************
|
|
TBitmap
|
|
******************************************************************************
|
|
|
|
*****************************************************************************
|
|
This file is part of the Lazarus Component Library (LCL)
|
|
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
}
|
|
|
|
function TestStreamIsBMP(const AStream: TStream): boolean;
|
|
var
|
|
Signature: array[0..1] of Char;
|
|
ReadSize: Integer;
|
|
OldPosition: TStreamSeekType;
|
|
begin
|
|
OldPosition:=AStream.Position;
|
|
ReadSize:=AStream.Read(Signature, SizeOf(Signature));
|
|
Result:=(ReadSize=2) and (Signature[0]='B') and (Signature[1]='M');
|
|
//debugln('TestStreamIsBMP ',DbgStr(Signature[0]),' ',DbgStr(Signature[1]));
|
|
AStream.Position:=OldPosition;
|
|
end;
|
|
|
|
type
|
|
|
|
{ THeaderStream }
|
|
|
|
THeaderStream = class(TStream)
|
|
private
|
|
FSource: TStream;
|
|
FSourceStart: Int64;
|
|
FHeadPos: Integer;
|
|
FHeadPtr: PByte;
|
|
FHeadSize: Integer;
|
|
protected
|
|
public
|
|
function Read(var Buffer; Count: Longint): Longint; override;
|
|
function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; override;
|
|
constructor Create(ASource: TStream; AHeader: Pointer; ASize: Integer);
|
|
end;
|
|
|
|
{ THeaderStream }
|
|
|
|
constructor THeaderStream.Create(ASource: TStream; AHeader: Pointer; ASize: Integer);
|
|
begin
|
|
inherited Create;
|
|
FSource := ASource;
|
|
FSourceStart := ASource.Position;
|
|
FHeadPtr := AHeader;
|
|
FHeadSize := ASize;
|
|
end;
|
|
|
|
function THeaderStream.Read(var Buffer; Count: Longint): Longint;
|
|
var
|
|
len: Integer;
|
|
buf: PByte;
|
|
begin
|
|
if Count <= 0 then Exit(0);
|
|
|
|
if FHeadPos < FHeadSize
|
|
then begin
|
|
len := Min(FHeadSize - FHeadPos, Count);
|
|
Move(FHeadPtr[FHeadPos], Buffer, len);
|
|
Dec(Count, len);
|
|
Inc(FHeadPos, len);
|
|
if Count = 0 then Exit(len);
|
|
buf := @Buffer;
|
|
Inc(buf, len);
|
|
end
|
|
else begin
|
|
len := 0;
|
|
buf := @Buffer;
|
|
end;
|
|
Result := FSource.Read(buf^, Count) + len;
|
|
end;
|
|
|
|
function THeaderStream.Seek(const Offset: Int64; Origin: TSeekOrigin): Int64;
|
|
begin
|
|
case Origin of
|
|
soBeginning: begin
|
|
Result := Offset;
|
|
end;
|
|
soCurrent: begin
|
|
Result := FHeadPos + Offset;
|
|
if FHeadPos = FHeadSize
|
|
then Inc(Result, FSource.Position);
|
|
end;
|
|
soEnd: begin
|
|
Result := FHeadSize + FSource.Size - FSourceStart + Offset;
|
|
end;
|
|
end;
|
|
|
|
if Result < FHeadSize
|
|
then begin
|
|
FHeadPos := Result;
|
|
FSource.Seek(FSourceStart, soBeginning);
|
|
end
|
|
else begin
|
|
FHeadPos := FHeadSize;
|
|
FSource.Seek(FSourceStart + Result - FHeadSize, soBeginning);
|
|
end;
|
|
end;
|
|
|
|
|
|
{ TBitmap }
|
|
|
|
class function TBitmap.GetFileExtensions: string;
|
|
begin
|
|
Result:='bmp';
|
|
end;
|
|
|
|
function TBitmap.GetResourceType: TResourceType;
|
|
begin
|
|
Result := RT_BITMAP;
|
|
end;
|
|
|
|
procedure TBitmap.LoadFromStream(AStream: TStream; ASize: Cardinal);
|
|
var
|
|
S: THeaderStream;
|
|
Header: TBitmapFileHeader;
|
|
begin
|
|
if AStream is TResourceStream then
|
|
begin
|
|
if TestStreamIsBMP(AStream) then
|
|
{ Handle the special case of an RC_RTDATA resource which contains a
|
|
complete, functional TBitmap structure (BitmapFileHeader+BitmapInfoHeader). }
|
|
inherited LoadFromStream(AStream, ASize)
|
|
else
|
|
begin
|
|
{ Normal case of an RT_BITMAP resource lacking the BitmapFileHeader }
|
|
FillChar(Header, SizeOf(Header), 0);
|
|
{ Create a BMP header ordered as it would be on disc, noting that if the CPU
|
|
is big-endian this will be the "wrong way round" for numeric operations. }
|
|
{$IFNDEF ENDIAN_BIG}
|
|
Header.bfType := $4d42;
|
|
Header.bfSize := SizeOf(Header) + ASize;
|
|
{$ELSE}
|
|
Header.bfType := $424d;
|
|
Header.bfSize := swap(SizeOf(Header) + ASize);
|
|
{$ENDIF}
|
|
//Header.bfOffBits := 0; //data follow immediately
|
|
|
|
S := THeaderStream.Create(AStream, @Header, SizeOf(Header));
|
|
try
|
|
inherited LoadFromStream(S, SizeOf(Header) + ASize);
|
|
finally
|
|
S.Free;
|
|
end;
|
|
end;
|
|
end
|
|
else
|
|
inherited LoadFromStream(AStream, ASize);
|
|
end;
|
|
|
|
class function TBitmap.GetReaderClass: TFPCustomImageReaderClass;
|
|
begin
|
|
Result := TLazReaderBMP;
|
|
end;
|
|
|
|
class function TBitmap.GetSharedImageClass: TSharedRasterImageClass;
|
|
begin
|
|
Result := TSharedBitmap;
|
|
end;
|
|
|
|
class function TBitmap.GetWriterClass: TFPCustomImageWriterClass;
|
|
begin
|
|
Result := TLazWriterBMP;
|
|
end;
|
|
|
|
procedure TBitmap.InitializeReader(AImage: TLazIntfImage; AReader: TFPCustomImageReader);
|
|
var
|
|
LazReader: TLazReaderBMP absolute AReader;
|
|
begin
|
|
inherited;
|
|
|
|
if not (AReader is TLazReaderBMP) then Exit;
|
|
|
|
// TransparentMode
|
|
// tmAuto: use left bottom pixel
|
|
// tmFixed: use color
|
|
//
|
|
// TransparentColor:
|
|
// clDefault: use left, bottom pixel color as transparent color (*)
|
|
// clNone: load image opaque (*)
|
|
// otherwise: use TransparentColor as transparent color
|
|
//
|
|
// (*) these are Lazarus extensions
|
|
|
|
if (TransparentMode = tmAuto) or (TransparentColor = clDefault)
|
|
then begin
|
|
LazReader.MaskMode := lrmmAuto;
|
|
end
|
|
else begin
|
|
if TransparentColor = clNone
|
|
then begin
|
|
LazReader.MaskMode := lrmmNone;
|
|
end
|
|
else begin
|
|
LazReader.MaskMode := lrmmColor;
|
|
LazReader.MaskColor := TColorToFPColor(TransparentColor);
|
|
end;
|
|
end;
|
|
end;
|
|
|