📄 gif_myrxgraph.pas
字号:
PByte(Dest)^ := Colors[C shr 4].rgbBlue;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C shr 4].rgbGreen;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C shr 4].rgbRed;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C and 15].rgbBlue;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C and 15].rgbGreen;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C and 15].rgbRed;
Dest := HugeOffset(Dest, 1);
Inc(X, 2);
end;
if X < Header.biWidth then begin
C := Byte(Src^);
PByte(Dest)^ := Colors[C shr 4].rgbBlue;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C shr 4].rgbGreen;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C shr 4].rgbRed;
{Dest := HugeOffset(Dest, 1);}
end;
end;
8:
begin
for X := 0 to Header.biWidth - 1 do begin
C := Byte(Src^);
Src := HugeOffset(Src, 1);
PByte(Dest)^ := Colors[C].rgbBlue;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C].rgbGreen;
Dest := HugeOffset(Dest, 1);
PByte(Dest)^ := Colors[C].rgbRed;
Dest := HugeOffset(Dest, 1);
end;
end;
end;
end;
end;
*)
{ DIB utility routines }
function GetPaletteBitmapFormat(Bitmap: TBitmap): TPixelFormat;
var
PalSize: Integer;
begin
Result := pfDevice;
if Bitmap.Palette <> 0 then begin
GetObject(Bitmap.Palette, SizeOf(Integer), @PalSize);
if PalSize > 0 then begin
if PalSize <= 2 then Result := pf1bit
else if PalSize <= 16 then Result := pf4bit
else if PalSize <= 256 then Result := pf8bit;
end;
end;
end;
function GetBitmapPixelFormat(Bitmap: TBitmap): TPixelFormat;
var
BM: Windows.TBitmap;
begin
Result := pfDevice;
if Bitmap.Handle <> 0 then begin
GetObject(Bitmap.Handle, SizeOf(BM), @BM);
case BM.bmBitsPixel * BM.bmPlanes of
1: Result := pf1bit;
4: Result := pf4bit;
8: Result := pf8bit;
24: Result := pf24bit;
end;
end;
end;
function BytesPerScanline(PixelsPerScanline, BitsPerPixel,
Alignment: Longint): Longint;
begin
Dec(Alignment);
Result := ((PixelsPerScanline * BitsPerPixel) + Alignment) and
not Alignment;
Result := Result div 8;
end;
procedure InitializeBitmapInfoHeader(Bitmap: HBITMAP; var BI: TBitmapInfoHeader;
PixelFormat: TPixelFormat);
var
DS: TDIBSection;
Bytes: Integer;
begin
DS.dsbmih.biSize := 0;
Bytes := GetObject(Bitmap, SizeOf(DS), @DS);
if Bytes = 0 then InvalidBitmap
else if (Bytes >= (SizeOf(DS.dsbm) + SizeOf(DS.dsbmih))) and
(DS.dsbmih.biSize >= DWORD(SizeOf(DS.dsbmih))) then
BI := DS.dsbmih
else begin
FillChar(BI, sizeof(BI), 0);
with BI, DS.dsbm do begin
biSize := SizeOf(BI);
biWidth := bmWidth;
biHeight := bmHeight;
end;
end;
case PixelFormat of
pf1bit: BI.biBitCount := 1;
pf4bit: BI.biBitCount := 4;
pf8bit: BI.biBitCount := 8;
pf24bit: BI.biBitCount := 24;
else BI.biBitCount := DS.dsbm.bmBitsPixel * DS.dsbm.bmPlanes;
end;
BI.biPlanes := 1;
if BI.biSizeImage = 0 then
BI.biSizeImage := BytesPerScanLine(BI.biWidth, BI.biBitCount, 32) * Abs(BI.biHeight);
end;
procedure InternalGetDIBSizes(Bitmap: HBITMAP; var InfoHeaderSize: Integer;
var ImageSize: Longint; BitCount: TPixelFormat);
var
BI: TBitmapInfoHeader;
begin
InitializeBitmapInfoHeader(Bitmap, BI, BitCount);
if BI.biBitCount > 8 then begin
InfoHeaderSize := SizeOf(TBitmapInfoHeader);
if (BI.biCompression and BI_BITFIELDS) <> 0 then
Inc(InfoHeaderSize, 12);
end
else InfoHeaderSize := SizeOf(TBitmapInfoHeader) + SizeOf(TRGBQuad) *
(1 shl BI.biBitCount);
ImageSize := BI.biSizeImage;
end;
function InternalGetDIB(Bitmap: HBITMAP; Palette: HPALETTE;
var BitmapInfo; var Bits; PixelFormat: TPixelFormat): Boolean;
var
OldPal: HPALETTE;
DC: HDC;
begin
InitializeBitmapInfoHeader(Bitmap, TBitmapInfoHeader(BitmapInfo), PixelFormat);
with TBitmapInfoHeader(BitmapInfo) do biHeight := Abs(biHeight);
OldPal := 0;
DC := CreateCompatibleDC(0);
try
if Palette <> 0 then
begin
OldPal := SelectPalette(DC, Palette, False);
RealizePalette(DC);
end;
Result := GetDIBits(DC, Bitmap, 0, TBitmapInfoHeader(BitmapInfo).biHeight,
@Bits, TBitmapInfo(BitmapInfo), DIB_RGB_COLORS) <> 0;
finally
if OldPal <> 0 then SelectPalette(DC, OldPal, False);
DeleteDC(DC);
end;
end;
function DIBFromBit(Src: HBITMAP; Pal: HPALETTE; PixelFormat: TPixelFormat;
var Length: Longint): Pointer;
var
HeaderSize: Integer;
ImageSize: Longint;
FileHeader: PBitmapFileHeader;
BI: PBitmapInfoHeader;
Bits: Pointer;
begin
if Src = 0 then InvalidBitmap;
InternalGetDIBSizes(Src, HeaderSize, ImageSize, PixelFormat);
Length := SizeOf(TBitmapFileHeader) + HeaderSize + ImageSize;
Result := AllocMemo(Length);
try
FillChar(Result^, Length, 0);
FileHeader := Result;
with FileHeader^ do
begin
bfType := $4D42;
bfSize := Length;
bfOffBits := SizeOf(FileHeader^) + HeaderSize;
end;
BI := PBitmapInfoHeader(Longint(FileHeader) + SizeOf(FileHeader^));
Bits := Pointer(Longint(BI) + HeaderSize);
InternalGetDIB(Src, Pal, BI^, Bits^, PixelFormat);
except
FreeMemo(Result);
raise;
end;
end;
{ Change bits per pixel in a General Bitmap }
function BitmapToMemoryStream(Bitmap: TBitmap; PixelFormat: TPixelFormat;
Method: TMappingMethod): TMemoryStream;
var
FileHeader: PBitmapFileHeader;
BI, NewBI: PBitmapInfoHeader;
Bits: Pointer;
NewPalette: PRGBPalette;
NewHeaderSize: Integer;
ImageSize, Length, Len: Longint;
P, InitData: Pointer;
ColorCount: Integer;
begin
if Bitmap.Handle = 0 then InvalidBitmap;
if (GetBitmapPixelFormat(Bitmap) = PixelFormat) and
(Method <> mmGrayscale) then
begin
Result := TMemoryStream.Create;
try
Bitmap.SaveToStream(Result);
Result.Position := 0;
except
Result.Free;
raise;
end;
Exit;
end;
if not (PixelFormat in [pf1bit, pf4bit, pf8bit, pf24bit]) then
NotImplemented
else if (PixelFormat in [pf1bit, pf4Bit]) then begin
P := DIBFromBit(Bitmap.Handle, Bitmap.Palette, PixelFormat, Length);
try
Result := TMemoryStream.Create;
try
Result.Write(P^, Length);
Result.Position := 0;
except
Result.Free;
raise;
end;
finally
FreeMemo(P);
end;
Exit;
end;
{ pf8bit - expand to 24bit first }
InitData := DIBFromBit(Bitmap.Handle, Bitmap.Palette, pf24bit, Len);
try
BI := PBitmapInfoHeader(Longint(InitData) + SizeOf(TBitmapFileHeader));
if BI^.biBitCount <> 24 then NotImplemented; {!!!}
Bits := Pointer(Longint(BI) + SizeOf(TBitmapInfoHeader));
InternalGetDIBSizes(Bitmap.Handle, NewHeaderSize, ImageSize, PixelFormat);
Length := SizeOf(TBitmapFileHeader) + NewHeaderSize;
P := AllocMemo(Length);
try
ZeroMemory(P, Length);
NewBI := PBitmapInfoHeader(Longint(P) + SizeOf(TBitmapFileHeader));
NewPalette := PRGBPalette(Longint(NewBI) + SizeOf(TBitmapInfoHeader));
FileHeader := PBitmapFileHeader(P);
InitializeBitmapInfoHeader(Bitmap.Handle, NewBI^, PixelFormat);
case Method of
mmQuantize:
begin
ColorCount := 256;
Quantize(BI^, Bits, Bits, ColorCount, NewPalette^);
NewBI^.biClrImportant := ColorCount;
end;
mmTrunc784:
begin
TruncPal7R8G4B(NewPalette^);
Trunc7R8G4B(BI^, Bits, Bits);
NewBI^.biClrImportant := 224;
end;
mmTrunc666:
begin
TruncPal6R6G6B(NewPalette^);
Trunc6R6G6B(BI^, Bits, Bits);
NewBI^.biClrImportant := 216;
end;
mmTripel:
begin
TripelPal(NewPalette^);
Tripel(BI^, Bits, Bits);
end;
mmHistogram:
begin
Histogram(BI^, NewPalette^, Bits, Bits,
PixelFormatToColors(PixelFormat), 255, 255, 255);
end;
mmGrayscale:
begin
GrayPal(NewPalette^);
GrayScale(BI^, Bits, Bits);
end;
end;
with FileHeader^ do begin
bfType := $4D42;
bfSize := Length;
bfOffBits := SizeOf(FileHeader^) + NewHeaderSize;
end;
Result := TMemoryStream.Create;
try
Result.Write(P^, Length);
Result.Write(Bits^, ImageSize);
Result.Position := 0;
except
Result.Free;
raise;
end;
finally
FreeMemo(P);
end;
finally
FreeMemo(InitData);
end;
end;
function BitmapToMemory(Bitmap: TBitmap; Colors: Integer): TStream;
var
PixelFormat: TPixelFormat;
begin
if Colors <= 2 then PixelFormat := pf1bit
else if Colors <= 16 then PixelFormat := pf4bit
else if Colors <= 256 then PixelFormat := pf8bit
else PixelFormat := pf24bit;
Result := BitmapToMemoryStream(Bitmap, PixelFormat, DefaultMappingMethod);
end;
procedure SaveBitmapToFile(const Filename: string; Bitmap: TBitmap;
Colors: Integer);
var
Memory: TStream;
begin
if Bitmap.Monochrome then Colors := 2;
Memory := BitmapToMemory(Bitmap, Colors);
try
TMemoryStream(Memory).SaveToFile(Filename);
finally
Memory.Free;
end;
end;
procedure SetBitmapPixelFormat(Bitmap: TBitmap; PixelFormat: TPixelFormat;
Method: TMappingMethod);
var
M: TMemoryStream;
begin
if (Bitmap.Handle = 0) or (GetBitmapPixelFormat(Bitmap) = PixelFormat) then
Exit;
M := BitmapToMemoryStream(Bitmap, PixelFormat, Method);
try
Bitmap.LoadFromStream(M);
finally
M.Free;
end;
end;
procedure GrayscaleBitmap(Bitmap: TBitmap);
begin
SetBitmapPixelFormat(Bitmap, pf8bit, mmGrayscale);
end;
function ZoomImage(ImageW, ImageH, MaxW, MaxH: Integer; Stretch: Boolean): TPoint;
var
Zoom: Double;
begin
Result := Point(0, 0);
if (MaxW <= 0) or (MaxH <= 0) or (ImageW <= 0) or (ImageH <= 0) then
Exit;
with Result do
if Stretch then begin
Zoom := MaxFloat([ImageW / MaxW, ImageH / MaxH]);
if (Zoom > 0) then begin
X := Round(ImageW * 0.98 / Zoom);
Y := Round(ImageH * 0.98 / Zoom);
end
else begin
X := ImageW;
Y := ImageH;
end;
end
else begin
X := MaxW;
Y := MaxH;
end;
end;
procedure TileImage(Canvas: TCanvas; Rect: TRect; Image: TGraphic);
var
X, Y: Integer;
SaveIndex: Integer;
begin
if (Image.Width = 0) or (Image.Height = 0) then Exit;
SaveIndex := SaveDC(Canvas.Handle);
try
with Rect do
IntersectClipRect(Canvas.Handle, Left, Top, Right, Bottom);
for X := 0 to (WidthOf(Rect) div Image.Width) do
for Y := 0 to (HeightOf(Rect) div Image.Height) do
Canvas.Draw(Rect.Left + X * Image.Width,
Rect.Top + Y * Image.Height, Image);
finally
RestoreDC(Canvas.Handle, SaveIndex);
end;
end;
{ TMyRxGradient }
constructor TMyRxGradient.Create;
begin
inherited Create;
FStartColor := clSilver;
FEndColor := clGray;
FStepCount := 64;
FDirection := fdTopToBottom;
end;
procedure TMyRxGradient.Assign(Source: TPersistent);
begin
if Source is TMyRxGradient then begin
with TMyRxGradient(Source) do begin
Self.FStartColor := StartColor;
Self.FEndColor := EndColor;
Self.FStepCount := StepCount;
Self.FDirection := Direction;
Self.FVisible := Visible;
end;
Changed;
end
else inherited Assign(Source);
end;
procedure TMyRxGradient.Changed;
begin
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure TMyRxGradient.Draw(Canvas: TCanvas; Rect: TRect);
begin
GradientFillRect(Canvas, Rect, FStartColor, FEndColor, FDirection,
FStepCount);
end;
procedure TMyRxGradient.SetStartColor(Value: TColor);
begin
if Value <> FStartColor then begin
FStartColor := Value;
Changed;
end;
end;
procedure TMyRxGradient.SetEndColor(Value: TColor);
begin
if Value <> FEndColor then begin
FEndColor := Value;
Changed;
end;
end;
procedure TMyRxGradient.SetDirection(Value: TFillDirection);
begin
if Value <> FDirection then begin
FDirection := Value;
Changed;
end;
end;
procedure TMyRxGradient.SetStepCount(Value: Byte);
begin
if Value <> FStepCount then begin
FStepCount := Value;
Changed;
end;
end;
procedure TMyRxGradient.SetVisible(Value: Boolean);
begin
if FVisible <> Value then begin
FVisible := Value;
Changed;
end;
end;
initialization
InitTruncTables;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -