📄 freebitmap.pas
字号:
x1 := 0;
x2 := trunc(xscale);
for x := 0 to w - 1 do
begin
lutX[x] := x2 - x1;
x1 := x2;
x2 := trunc((x + 2) * xscale);
end;
// Y lookup table
SetLength(lutY, h);
x1 := 0;
x2 := trunc(yscale);
for x := 0 to h - 1 do
begin
lutY[x] := x2 - x1;
x1 := x2;
x2 := trunc((x + 2) * yscale);
end;
Dec(w);
Dec(h);
RowDest := integer(FreeImage_GetScanLine(DestBmp, 0));
RowSourceStart := integer(FreeImage_GetScanLine(SrcBmp, 0));
RowSource := RowSourceStart;
for y := 0 to h do
// resampling
begin
dy := lutY[y];
x1 := 0;
x3 := 0;
for x := 0 to w do // loop through row
begin
dx:= lutX[x];
iRed:= 0;
iGrn:= 0;
iBlu:= 0;
RowSource := RowSourceStart;
for iy := 1 to dy do
begin
pt := PRGB24(RowSource + x1);
for ix := 1 to dx do
begin
iRed := iRed + pt.R;
iGrn := iGrn + pt.G;
iBlu := iBlu + pt.B;
inc(pt);
end;
RowSource := RowSource + iSrc;
end;
iRatio := 65535 div (dx * dy);
pt1 := PRGB24(RowDest + x3);
pt1.R := (iRed * iRatio) shr 16;
pt1.G := (iGrn * iRatio) shr 16;
pt1.B := (iBlu * iRatio) shr 16;
x1 := x1 + 3 * dx;
inc(x3,3);
end;
RowDest := RowDest + iDst;
RowSourceStart := RowSource;
end; // resampling
if FreeImage_GetHeight(DestBmp) >= 3 then
// Sharpening...
begin
s1 := integer(FreeImage_GetScanLine(DestBmp, 0));
iDst := integer(FreeImage_GetScanLine(DestBmp, 1)) - s1;
ny1 := Integer(s1);
ny2 := ny1 + iDst;
ny3 := ny2 + iDst;
for y := 1 to FreeImage_GetHeight(DestBmp) - 2 do
begin
for x := 0 to FreeImage_GetWidth(DestBmp) - 3 do
begin
x1 := x * 3;
x2 := x1 + 3;
x3 := x1 + 6;
c1 := pRGB24(ny1 + x1)^;
c2 := pRGB24(ny1 + x3)^;
c3 := pRGB24(ny2 + x2)^;
c4 := pRGB24(ny3 + x1)^;
c5 := pRGB24(ny3 + x3)^;
r := (c1.R + c2.R + (c3.R * -12) + c4.R + c5.R) div -8;
g := (c1.G + c2.G + (c3.G * -12) + c4.G + c5.G) div -8;
b := (c1.B + c2.B + (c3.B * -12) + c4.B + c5.B) div -8;
if r < 0 then r := 0 else if r > 255 then r := 255;
if g < 0 then g := 0 else if g > 255 then g := 255;
if b < 0 then b := 0 else if b > 255 then b := 255;
pt1 := pRGB24(ny2 + x2);
pt1.R := r;
pt1.G := g;
pt1.B := b;
end;
inc(ny1, iDst);
inc(ny2, iDst);
inc(ny3, iDst);
end;
end; // sharpening
if SrcBmp <> FDib then
FreeImage_Unload(SrcBmp);
DestBitmap.Replace(DestBmp);
end;
function TFreeBitmap.PasteSubImage(Src: TFreeBitmap; Left, Top,
Alpha: Integer): Boolean;
begin
if FDib <> nil then
begin
Result := FreeImage_Paste(FDib, Src.Dib, Left, Top, Alpha);
Change;
end else
Result := False;
end;
function TFreeBitmap.Replace(NewDib: PFIBITMAP): Boolean;
begin
Result := False;
if NewDib = nil then Exit;
if not DoChanging(FDib, NewDib) and IsValid then
FreeImage_Unload(FDib);
FDib := NewDib;
Result := True;
Change;
end;
function TFreeBitmap.Rescale(NewWidth, NewHeight: Integer;
Filter: FREE_IMAGE_FILTER; Dest: TFreeBitmap): Boolean;
var
Bpp: Integer;
DstDib: PFIBITMAP;
begin
Result := False;
if FDib <> nil then
begin
Bpp := FreeImage_GetBPP(FDib);
if Bpp < 8 then
if not ConvertToGrayscale then Exit
else
if Bpp = 16 then
// convert to 24-bit
if not ConvertTo24Bits then Exit;
// perform upsampling / downsampling
DstDib := FreeImage_Rescale(FDib, NewWidth, NewHeight, Filter);
if Dest = nil then
Result := Replace(DstDib)
else
Result := Dest.Replace(DstDib)
end
end;
function TFreeBitmap.Rotate(Angle: Double): Boolean;
var
Bpp: Integer;
Rotated: PFIBITMAP;
begin
Result := False;
if IsValid then
begin
Bpp := FreeImage_GetBPP(FDib);
if Bpp in [1, 8, 24, 32] then
begin
Rotated := FreeImage_RotateClassic(FDib, Angle);
Result := Replace(Rotated);
end
end;
end;
function TFreeBitmap.RotateEx(Angle, XShift, YShift, XOrigin,
YOrigin: Double; UseMask: Boolean): Boolean;
var
Rotated: PFIBITMAP;
begin
Result := False;
if FDib <> nil then
begin
if FreeImage_GetBPP(FDib) >= 8 then
begin
Rotated := FreeImage_RotateEx(FDib, Angle, XShift, YShift, XOrigin, YOrigin, UseMask);
Result := Replace(Rotated);
end
end;
end;
function TFreeBitmap.Save(const FileName: string; Flag: Integer): Boolean;
var
fif: FREE_IMAGE_FORMAT;
begin
Result := False;
// try to guess the file format from the file extension
fif := FreeImage_GetFIFFromFilename(PChar(Filename));
if CanSave(fif) then
Result := FreeImage_Save(fif, FDib, PChar(FileName), Flag);
end;
function TFreeBitmap.SaveToHandle(fif: FREE_IMAGE_FORMAT; IO: PFreeImageIO;
Handle: fi_handle; Flag: Integer): Boolean;
begin
Result := False;
if CanSave(fif) then
Result := FreeImage_SaveToHandle(fif, FDib, IO, Handle, Flag)
end;
function TFreeBitmap.SaveToMemory(fif: FREE_IMAGE_FORMAT;
MemIO: TFreeMemoryIO; Flag: Integer): Boolean;
begin
Result := False;
if CanSave(fif) then
Result := MemIO.Write(fif, FDib, Flag)
end;
function TFreeBitmap.SaveToStream(fif: FREE_IMAGE_FORMAT; Stream: TStream;
Flag: Integer): Boolean;
var
MemIO: TFreeMemoryIO;
Data: PByte;
Size: Cardinal;
begin
MemIO := TFreeMemoryIO.Create;
try
Result := SaveToMemory(fif, MemIO, Flag);
if Result then
begin
MemIO.Acquire(Data, Size);
Stream.WriteBuffer(Data^, Size);
end;
finally
MemIO.Free;
end;
end;
function TFreeBitmap.SaveU(const FileName: WideString;
Flag: Integer): Boolean;
var
fif: FREE_IMAGE_FORMAT;
begin
Result := False;
// try to guess the file format from the file extension
fif := FreeImage_GetFIFFromFilenameU(PWideChar(Filename));
if CanSave(fif) then
Result := FreeImage_SaveU(fif, FDib, PWideChar(FileName), Flag);
end;
function TFreeBitmap.SetChannel(Bitmap: TFreeBitmap;
Channel: FREE_IMAGE_COLOR_CHANNEL): Boolean;
begin
if FDib <> nil then
begin
Result := FreeImage_SetChannel(FDib, Bitmap.FDib, Channel);
Change;
end
else
Result := False
end;
procedure TFreeBitmap.SetDib(Value: PFIBITMAP);
begin
Replace(Value);
end;
function TFreeBitmap.SetFileBkColor(BkColor: PRGBQuad): Boolean;
begin
Result := FreeImage_SetBackgroundColor(FDib, BkColor);
Change;
end;
procedure TFreeBitmap.SetHorizontalResolution(Value: Double);
begin
if IsValid then
begin
FreeImage_SetDotsPerMeterX(FDib, Trunc(Value * 100 + 0.5));
Change;
end;
end;
function TFreeBitmap.SetMetadata(Model: FREE_IMAGE_MDMODEL;
const Key: string; Tag: TFreeTag): Boolean;
begin
Result := FreeImage_SetMetadata(Model, FDib, PChar(Key), Tag.Tag);
end;
function TFreeBitmap.SetPixelColor(X, Y: Cardinal;
Value: PRGBQUAD): Boolean;
begin
Result := FreeImage_SetPixelColor(FDib, X, Y, Value);
Change;
end;
function TFreeBitmap.SetPixelIndex(X, Y: Cardinal; Value: PByte): Boolean;
begin
Result := FreeImage_SetPixelIndex(FDib, X, Y, Value);
Change;
end;
function TFreeBitmap.SetSize(ImageType: FREE_IMAGE_TYPE; Width, Height,
Bpp: Integer; RedMask, GreenMask, BlueMask: Cardinal): Boolean;
var
Pal: PRGBQuad;
I: Cardinal;
begin
Result := False;
if FDib <> nil then
FreeImage_Unload(FDib);
FDib := FreeImage_Allocate(Width, Height, Bpp, RedMask, GreenMask, BlueMask);
if FDib = nil then Exit;
if ImageType = FIT_BITMAP then
case Bpp of
1, 4, 8:
begin
Pal := FreeImage_GetPalette(FDib);
for I := 0 to FreeImage_GetColorsUsed(FDib) - 1 do
begin
Pal.rgbBlue := I;
Pal.rgbGreen := I;
Pal.rgbRed := I;
Inc(Pal, SizeOf(RGBQUAD));
end;
end;
end;
Result := True;
Change;
end;
procedure TFreeBitmap.SetTransparencyTable(Table: PByte; Count: Integer);
begin
FreeImage_SetTransparencyTable(FDib, Table, Count);
Change;
end;
procedure TFreeBitmap.SetVerticalResolution(Value: Double);
begin
if IsValid then
begin
FreeImage_SetDotsPerMeterY(FDib, Trunc(Value * 100 + 0.5));
Change;
end;
end;
function TFreeBitmap.SplitChannels(RedChannel, GreenChannel,
BlueChannel: TFreeBitmap): Boolean;
begin
if FDib <> nil then
begin
RedChannel.FDib := FreeImage_GetChannel(FDib, FICC_RED);
GreenChannel.FDib := FreeImage_GetChannel(FDib, FICC_GREEN);
BlueChannel.FDib := FreeImage_GetChannel(FDib, FICC_BLUE);
Result := RedChannel.IsValid and GreenChannel.IsValid and BlueChannel.IsValid;
end
else
Result := False
end;
function TFreeBitmap.Threshold(T: Byte): Boolean;
var
dib1: PFIBITMAP;
begin
if FDib <> nil then
begin
dib1 := FreeImage_Threshold(FDib, T);
Result := Replace(dib1);
end
else
Result := False
end;
function TFreeBitmap.ToneMapping(TMO: FREE_IMAGE_TMO; FirstParam,
SecondParam: Double): Boolean;
var
NewDib: PFIBITMAP;
begin
Result := False;
if not IsValid then Exit;
NewDib := FreeImage_ToneMapping(Fdib, TMO, FirstParam, SecondParam);
Result := Replace(NewDib);
end;
{ TFreeWinBitmap }
function TFreeWinBitmap.CaptureWindow(ApplicationWindow,
SelectedWindow: HWND): Boolean;
var
XScreen, YScreen, XShift, YShift, Width, Height: Integer;
R: TRect;
dstDC, srcDC, memDC: HDC;
BM, oldBM: HBITMAP;
begin
Result := False;
// get window size
GetWindowRect(SelectedWindow, R);
// check if the window is out of screen or maximized
XShift := 0;
YShift := 0;
XScreen := GetSystemMetrics(SM_CXSCREEN);
YScreen := GetSystemMetrics(SM_CYSCREEN);
if R.Right > XScreen then
R.Right := XScreen;
if R.Bottom > YScreen then
R.Bottom := YScreen;
if R.Left < 0 then
begin
XShift := -R.Left;
R.Left := 0;
end;
if R.Top < 0 then
begin
YShift := -R.Top;
R.Top := 0;
end;
Width := R.Right - R.Left;
Height := R.Bottom - R.Top;
if (Width <= 0) or (Height <= 0) then Exit;
// hide the application window
ShowWindow(ApplicationWindow, SW_HIDE);
// bring the window at the top most level
SetWindowPos(SelectedWindow, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
// give enough time to refresh the window
Sleep(500);
// prepare the DCs
dstDc := GetDC(0);
srcDC := GetWindowDC(SelectedWindow); //full window (GetDC(SelectedWindow) = clientarea)
memDC := CreateCompatibleDC(dstDC);
// copy the screen to the bitmap
BM := CreateCompatibleBitmap(dstDC, Width, Height);
oldBM := HBITMAP(SelectObject(memDC, BM));
BitBlt(memDC, 0, 0, Width, Height, srcDC, XShift, YShift, SRCCOPY);
// redraw the application window
ShowWindow(ApplicationWindow, SW_SHOW);
// restore the position
SetWindowPos(SelectedWindow, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
SetWindowPos(ApplicationWindow, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
// convert the HBITMAP to FIBITMAP
CopyFromBitmap(BM);
// free objects
DeleteObject(SelectObject(memDC, oldBM));
DeleteObject(memDC);
if GetBitsPerPixel = 32 then ConvertTo24Bits;
Result := True;
end;
procedure TFreeWinBitmap.Clear;
begin
if FDeleteMe then FreeImage_Unload(FDisplayDib);
inherited;
end;
function TFreeWinBitmap.CopyFromBitmap(HBmp: HBITMAP): Boolean;
var
bm: BITMAP;
DC: HDC;
Success: Integer;
begin
Result := False;
if HBmp <> 0 then
begin
// get information about the bitmap
GetObject(HBmp, SizeOf(BITMAP), @bm);
// create the image
SetSize(FIT_BITMAP, bm.bmWidth, bm.bmHeight, bm.bmBitsPixel);
// create the device context for the bitmap
DC := GetDC(0);
// copy the pixels
Success := GetDIBits(DC, // handle to DC
HBmp, // handle to Bitmap
0, // first scan line
FreeImage_GetHeight(Dib), // number of scan lines to copy
FreeImage_GetBits(Dib), // array for bitmap bits
FreeImage_GetInfo(Dib^)^, // bitmap data buffer
DIB_RGB_COLORS // RGB
);
ReleaseDC(0, DC);
if Success = 0 then
raise Exception.Create('Error: GetDIBits failed')
else
Result := True;
end;
end;
function TFreeWinBitmap.CopyFromHandle(HMem: THandle): Boolean;
var
Data: PByte;
bmih: PBitmapInfoHeader;
Palette: PRGBQuad;
Bits: PByte;
BitFields: array [0..2] of DWORD;
MaskSize: Longint;
image_type: FREE_IMAGE_TYPE;
begin
Result := False;
Palette := nil;
BitFields[0] := 0; BitFields[1] := 0; BitFields[2] := 0;
// get a pointer to the bitmap
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -