You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
525 lines
14 KiB
525 lines
14 KiB
3 years ago
|
unit MainFrm;
|
||
|
|
||
|
interface
|
||
|
|
||
|
uses
|
||
|
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
|
||
|
Dialogs, Menus, ExtCtrls, Math, GR32, GR32_Image, GR32_Transforms,
|
||
|
ExtDlgs;
|
||
|
|
||
|
type
|
||
|
TMainForm = class(TForm)
|
||
|
PopupMenu: TPopupMenu;
|
||
|
ZoomInItem: TMenuItem;
|
||
|
ZoomOutItem: TMenuItem;
|
||
|
ActualSizeItem: TMenuItem;
|
||
|
ImgView32: TImgView32;
|
||
|
N1: TMenuItem;
|
||
|
AlphaView: TImgView32;
|
||
|
ShowAlphaItem: TMenuItem;
|
||
|
RotateClockwiseItem: TMenuItem;
|
||
|
RotateAntiClockwiseItem: TMenuItem;
|
||
|
N3: TMenuItem;
|
||
|
ShowWithAlphaItem: TMenuItem;
|
||
|
N4: TMenuItem;
|
||
|
FlipHorizontalItem: TMenuItem;
|
||
|
FilpVerticalItem: TMenuItem;
|
||
|
FilterTimer: TTimer;
|
||
|
OpenImageItem: TMenuItem;
|
||
|
N2: TMenuItem;
|
||
|
OpenDialog: TOpenDialog;
|
||
|
procedure FormCreate(Sender: TObject);
|
||
|
procedure FormDestroy(Sender: TObject);
|
||
|
procedure FormShow(Sender: TObject);
|
||
|
procedure ZoomInItemClick(Sender: TObject);
|
||
|
procedure ZoomOutItemClick(Sender: TObject);
|
||
|
procedure ActualSizeItemClick(Sender: TObject);
|
||
|
procedure ScrollBoxMouseWheel(Sender: TObject; Shift: TShiftState;
|
||
|
WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
|
||
|
procedure FormKeyUp(Sender: TObject; var Key: Word;
|
||
|
Shift: TShiftState);
|
||
|
procedure ShowAlphaItemClick(Sender: TObject);
|
||
|
procedure RotateClockwiseItemClick(Sender: TObject);
|
||
|
procedure RotateAntiClockwiseItemClick(Sender: TObject);
|
||
|
procedure ShowWithAlphaItemClick(Sender: TObject);
|
||
|
procedure FlipHorizontalItemClick(Sender: TObject);
|
||
|
procedure FilpVerticalItemClick(Sender: TObject);
|
||
|
procedure FilterTimerTimer(Sender: TObject);
|
||
|
procedure ImgView32Scroll(Sender: TObject);
|
||
|
procedure OpenImageItemClick(Sender: TObject);
|
||
|
private
|
||
|
{ Private declarations }
|
||
|
OrigWidth : integer;
|
||
|
OrigHeight : integer;
|
||
|
BPP : longword;
|
||
|
|
||
|
procedure LoadImage( Name : string);
|
||
|
procedure RecalcWindowSize;
|
||
|
public
|
||
|
{ Public declarations }
|
||
|
end;
|
||
|
|
||
|
var
|
||
|
MainForm: TMainForm;
|
||
|
|
||
|
implementation
|
||
|
|
||
|
{$R *.dfm}
|
||
|
|
||
|
uses FreeImage, GR32_Resamplers;
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.FormCreate(Sender: TObject);
|
||
|
begin
|
||
|
AlphaView.Visible := False;
|
||
|
AlphaView.Align := alClient;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.FormDestroy(Sender: TObject);
|
||
|
begin
|
||
|
// ...
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.FormShow(Sender: TObject);
|
||
|
var
|
||
|
Resampler: TKernelResampler;
|
||
|
begin
|
||
|
Resampler := TKernelResampler.Create(ImgView32.Bitmap);
|
||
|
Resampler.Kernel := TSplineKernel.Create;
|
||
|
if ParamCount = 1 then
|
||
|
LoadImage(ParamStr(1));
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.LoadImage( Name : string);
|
||
|
var
|
||
|
dib : PFIBITMAP;
|
||
|
PBH : PBITMAPINFOHEADER;
|
||
|
PBI : PBITMAPINFO;
|
||
|
t : FREE_IMAGE_FORMAT;
|
||
|
Ext : string;
|
||
|
BM : TBitmap;
|
||
|
x, y : integer;
|
||
|
BP : PLONGWORD;
|
||
|
DC : HDC;
|
||
|
begin
|
||
|
try
|
||
|
t := FreeImage_GetFileType(PAnsiChar(AnsiString(Name)), 16);
|
||
|
|
||
|
if t = FIF_UNKNOWN then
|
||
|
begin
|
||
|
// Check for types not supported by GetFileType
|
||
|
Ext := UpperCase(ExtractFileExt(Name));
|
||
|
if (Ext = '.TGA') or(Ext = '.TARGA') then
|
||
|
t := FIF_TARGA
|
||
|
else if Ext = '.MNG' then
|
||
|
t := FIF_MNG
|
||
|
else if Ext = '.PCD' then
|
||
|
t := FIF_PCD
|
||
|
else if Ext = '.WBMP' then
|
||
|
t := FIF_WBMP
|
||
|
else if Ext = '.CUT' then
|
||
|
t := FIF_CUT
|
||
|
else
|
||
|
raise Exception.Create('The file "' + Name + '" cannot be displayed because SFM does not recognise the file type.');
|
||
|
end;
|
||
|
|
||
|
dib := FreeImage_Load(t, PAnsiChar(AnsiString(name)), 0);
|
||
|
if Dib = nil then
|
||
|
Close;
|
||
|
PBH := FreeImage_GetInfoHeader(dib);
|
||
|
PBI := FreeImage_GetInfo(dib);
|
||
|
|
||
|
BPP := FreeImage_GetBPP(dib);
|
||
|
|
||
|
ShowWithAlphaItem.Enabled := BPP = 32;
|
||
|
ShowAlphaItem.Enabled := BPP = 32;
|
||
|
|
||
|
if BPP = 32 then
|
||
|
begin
|
||
|
ImgView32.Bitmap.SetSize(FreeImage_GetWidth(dib), FreeImage_GetHeight(dib));
|
||
|
|
||
|
BP := PLONGWORD(FreeImage_GetBits(dib));
|
||
|
for y := ImgView32.Bitmap.Height - 1 downto 0 do
|
||
|
for x := 0 to ImgView32.Bitmap.Width - 1 do
|
||
|
begin
|
||
|
ImgView32.Bitmap.Pixel[x, y] := BP^;
|
||
|
inc(BP);
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
BM := TBitmap.Create;
|
||
|
|
||
|
BM.Assign(nil);
|
||
|
DC := GetDC(Handle);
|
||
|
|
||
|
BM.handle := CreateDIBitmap(DC,
|
||
|
PBH^,
|
||
|
CBM_INIT,
|
||
|
PChar(FreeImage_GetBits(dib)),
|
||
|
PBI^,
|
||
|
DIB_RGB_COLORS);
|
||
|
|
||
|
ImgView32.Bitmap.Assign(BM);
|
||
|
AlphaView.Bitmap.Assign(BM);
|
||
|
|
||
|
BM.Free;
|
||
|
ReleaseDC(Handle, DC);
|
||
|
end;
|
||
|
FreeImage_Unload(dib);
|
||
|
|
||
|
OrigWidth := ImgView32.Bitmap.Width;
|
||
|
OrigHeight := ImgView32.Bitmap.Height;
|
||
|
|
||
|
Caption := ExtractFileName( Name ) + ' (' + IntToStr(OrigWidth) +
|
||
|
' x ' + IntToStr(OrigHeight) + ')';
|
||
|
if BPP = 32 then
|
||
|
Caption := Caption + ' + Alpha';
|
||
|
|
||
|
AlphaView.Bitmap.SetSize(OrigWidth, OrigWidth);
|
||
|
|
||
|
ImgView32.Hint := 'Name: ' + Name + #13 +
|
||
|
'Width: ' + IntToStr(OrigWidth) + #13 +
|
||
|
'Height: ' + IntToStr(OrigHeight) + #13 +
|
||
|
'BPP: ' + IntToStr(BPP);
|
||
|
|
||
|
RecalcWindowSize;
|
||
|
|
||
|
Show;
|
||
|
except
|
||
|
on e:exception do
|
||
|
begin
|
||
|
Application.BringToFront;
|
||
|
MessageDlg(e.message, mtInformation, [mbOK], 0);
|
||
|
Close;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.ZoomInItemClick(Sender: TObject);
|
||
|
begin
|
||
|
FilterTimer.Enabled := False;
|
||
|
if not (ImgView32.Bitmap.Resampler is TNearestResampler) then
|
||
|
TNearestResampler.Create(ImgView32.Bitmap);
|
||
|
FilterTimer.Enabled := True;
|
||
|
|
||
|
ImgView32.Scale := ImgView32.Scale * 2.0;
|
||
|
RecalcWindowSize;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.ZoomOutItemClick(Sender: TObject);
|
||
|
begin
|
||
|
FilterTimer.Enabled := False;
|
||
|
if not (ImgView32.Bitmap.Resampler is TNearestResampler) then
|
||
|
TNearestResampler.Create(ImgView32.Bitmap);
|
||
|
FilterTimer.Enabled := True;
|
||
|
|
||
|
ImgView32.Scale := ImgView32.Scale / 2.0;
|
||
|
RecalcWindowSize;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.ActualSizeItemClick(Sender: TObject);
|
||
|
begin
|
||
|
FilterTimer.Enabled := False;
|
||
|
if not (ImgView32.Bitmap.Resampler is TNearestResampler) then
|
||
|
TNearestResampler.Create(ImgView32.Bitmap);
|
||
|
FilterTimer.Enabled := True;
|
||
|
|
||
|
ImgView32.Scale := 1.0;
|
||
|
|
||
|
RecalcWindowSize;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.RecalcWindowSize;
|
||
|
var
|
||
|
Rect : TRect;
|
||
|
CW, CH : integer;
|
||
|
WSH, WSW : integer;
|
||
|
TitleH : integer;
|
||
|
BorderY : integer;
|
||
|
BorderX : integer;
|
||
|
begin
|
||
|
CW := ImgView32.Bitmap.Width + GetSystemMetrics(SM_CXVSCROLL);
|
||
|
CH := ImgView32.Bitmap.Height + GetSystemMetrics(SM_CYVSCROLL);
|
||
|
|
||
|
SystemParametersInfo( SPI_GETWORKAREA, 0, @Rect, 0);
|
||
|
|
||
|
WSH := Rect.Bottom - Rect.Top;
|
||
|
WSW := Rect.Right - Rect.Left;
|
||
|
TitleH := GetSystemMetrics(SM_CYCAPTION);
|
||
|
BorderY := GetSystemMetrics(SM_CYSIZEFRAME) * 2;
|
||
|
BorderX := GetSystemMetrics(SM_CXSIZEFRAME) * 2;
|
||
|
|
||
|
if (Top + CH + TitleH + BorderY > WSH) or (CH + TitleH + BorderY > WSH) then
|
||
|
begin
|
||
|
Top := Rect.Bottom - CH - BorderY;
|
||
|
if Top < 0 then
|
||
|
begin
|
||
|
Top := 0;
|
||
|
CH := WSH - TitleH - BorderY;
|
||
|
CW := CW + GetSystemMetrics(SM_CXVSCROLL);
|
||
|
|
||
|
if CW + BorderX > WSW then
|
||
|
CH := CH - GetSystemMetrics(SM_CYVSCROLL);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
if (Left + CW + BorderX > WSW) or (CW + BorderX > WSW) then
|
||
|
begin
|
||
|
Left := Rect.Right - CW - BorderX;
|
||
|
if Left < 0 then
|
||
|
begin
|
||
|
Left := 0;
|
||
|
CW := WSW - BorderX;
|
||
|
CH := CH + GetSystemMetrics(SM_CYVSCROLL);
|
||
|
|
||
|
if CH + TitleH + BorderY > WSH then
|
||
|
CW := CW + GetSystemMetrics(SM_CXVSCROLL);
|
||
|
end
|
||
|
end;
|
||
|
|
||
|
ClientWidth := CW;
|
||
|
ClientHeight := CH;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.ScrollBoxMouseWheel(Sender: TObject;
|
||
|
Shift: TShiftState; WheelDelta: Integer; MousePos: TPoint;
|
||
|
var Handled: Boolean);
|
||
|
begin
|
||
|
FilterTimer.Enabled := False;
|
||
|
if not (ImgView32.Bitmap.Resampler is TNearestResampler) then
|
||
|
TNearestResampler.Create(ImgView32.Bitmap);
|
||
|
FilterTimer.Enabled := True;
|
||
|
|
||
|
if WheelDelta < 0 then
|
||
|
ImgView32.Scroll(0, 20)
|
||
|
else
|
||
|
ImgView32.Scroll(0, -20);
|
||
|
Handled := True;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.FormKeyUp(Sender: TObject; var Key: Word;
|
||
|
Shift: TShiftState);
|
||
|
var
|
||
|
Amount : integer;
|
||
|
begin
|
||
|
FilterTimer.Enabled := False;
|
||
|
if not (ImgView32.Bitmap.Resampler is TNearestResampler) then
|
||
|
TNearestResampler.Create(ImgView32.Bitmap);
|
||
|
FilterTimer.Enabled := True;
|
||
|
|
||
|
if ssShift in Shift then
|
||
|
Amount := 20 * 2
|
||
|
else
|
||
|
Amount := 20;
|
||
|
|
||
|
case Key of
|
||
|
VK_ESCAPE:
|
||
|
Close;
|
||
|
VK_UP:
|
||
|
ImgView32.Scroll(0, -Amount);
|
||
|
VK_DOWN:
|
||
|
ImgView32.Scroll(0, Amount);
|
||
|
VK_LEFT:
|
||
|
ImgView32.Scroll(-Amount, 0);
|
||
|
VK_RIGHT:
|
||
|
ImgView32.Scroll(Amount, 0);
|
||
|
VK_HOME:
|
||
|
ImgView32.ScrollToCenter(0, 0);
|
||
|
VK_END:
|
||
|
ImgView32.ScrollToCenter(ImgView32.Bitmap.Width, ImgView32.Bitmap.Height);
|
||
|
VK_NEXT:
|
||
|
ImgView32.Scroll(0, (Trunc(ImgView32.Bitmap.Height div 4)));
|
||
|
VK_PRIOR:
|
||
|
ImgView32.Scroll(0, -(Trunc(ImgView32.Bitmap.Height div 4)));
|
||
|
end;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.ShowAlphaItemClick(Sender: TObject);
|
||
|
var
|
||
|
x, y : integer;
|
||
|
Col : TColor32;
|
||
|
Alpha : TColor;
|
||
|
begin
|
||
|
if ShowAlphaItem.Checked then
|
||
|
begin
|
||
|
AlphaView.Visible := False;
|
||
|
AlphaView.Bitmap.Delete;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
AlphaView.Bitmap.Width := ImgView32.Bitmap.Width;
|
||
|
AlphaView.Bitmap.Height := ImgView32.Bitmap.Height;
|
||
|
|
||
|
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||
|
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||
|
begin
|
||
|
Col := ImgView32.Bitmap.Pixel[x, y];
|
||
|
Alpha := Col shr 24;
|
||
|
AlphaView.Bitmap.Pixel[x, y] := Alpha + (Alpha shl 8) + (Alpha shl 16);
|
||
|
end;
|
||
|
AlphaView.Visible := True;
|
||
|
end;
|
||
|
ShowAlphaItem.Checked := not ShowAlphaItem.Checked;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.RotateClockwiseItemClick(Sender: TObject);
|
||
|
var
|
||
|
x : integer;
|
||
|
y : integer;
|
||
|
DestX : integer;
|
||
|
DestY : integer;
|
||
|
C : TColor32;
|
||
|
begin
|
||
|
AlphaView.Bitmap.Assign(ImgView32.Bitmap);
|
||
|
|
||
|
ImgView32.BeginUpdate;
|
||
|
ImgView32.Bitmap.Width := AlphaView.Bitmap.Height;
|
||
|
ImgView32.Bitmap.Height := AlphaView.Bitmap.Width;
|
||
|
|
||
|
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||
|
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||
|
begin
|
||
|
C := AlphaView.Bitmap.Pixel[x, y];
|
||
|
|
||
|
DestX := (ImgView32.Bitmap.Width - 1) - Y;
|
||
|
DestY := X;
|
||
|
|
||
|
ImgView32.Bitmap.Pixels[DestX, DestY] := C;
|
||
|
end;
|
||
|
|
||
|
ImgView32.EndUpdate;
|
||
|
ImgView32.Refresh;
|
||
|
end;
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.RotateAntiClockwiseItemClick(Sender: TObject);
|
||
|
var
|
||
|
x : integer;
|
||
|
y : integer;
|
||
|
DestX : integer;
|
||
|
DestY : integer;
|
||
|
C : TColor32;
|
||
|
begin
|
||
|
AlphaView.Bitmap.Assign(ImgView32.Bitmap);
|
||
|
|
||
|
ImgView32.BeginUpdate;
|
||
|
ImgView32.Bitmap.Width := AlphaView.Bitmap.Height;
|
||
|
ImgView32.Bitmap.Height := AlphaView.Bitmap.Width;
|
||
|
|
||
|
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||
|
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||
|
begin
|
||
|
C := AlphaView.Bitmap.Pixel[x, y];
|
||
|
|
||
|
DestX := Y;
|
||
|
DestY := (ImgView32.Bitmap.Height - 1) -X;
|
||
|
|
||
|
ImgView32.Bitmap.Pixels[DestX, DestY] := C;
|
||
|
end;
|
||
|
|
||
|
ImgView32.EndUpdate;
|
||
|
ImgView32.Refresh;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.ShowWithAlphaItemClick(Sender: TObject);
|
||
|
begin
|
||
|
if ShowWithAlphaItem.Checked then
|
||
|
ImgView32.Bitmap.DrawMode := dmOpaque
|
||
|
else
|
||
|
ImgView32.Bitmap.DrawMode := dmBlend;
|
||
|
ShowWithAlphaItem.Checked := not ShowWithAlphaItem.Checked;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.FlipHorizontalItemClick(Sender: TObject);
|
||
|
var
|
||
|
x : integer;
|
||
|
y : integer;
|
||
|
DestX : integer;
|
||
|
DestY : integer;
|
||
|
C : TColor32;
|
||
|
begin
|
||
|
AlphaView.Bitmap.Assign(ImgView32.Bitmap);
|
||
|
|
||
|
ImgView32.BeginUpdate;
|
||
|
ImgView32.Bitmap.Width := AlphaView.Bitmap.Width;
|
||
|
ImgView32.Bitmap.Height := AlphaView.Bitmap.Height;
|
||
|
|
||
|
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||
|
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||
|
begin
|
||
|
C := AlphaView.Bitmap.Pixel[x, y];
|
||
|
|
||
|
DestX := (ImgView32.Bitmap.Width - 1) -X;
|
||
|
DestY := Y;
|
||
|
|
||
|
ImgView32.Bitmap.Pixels[DestX, DestY] := C;
|
||
|
end;
|
||
|
|
||
|
ImgView32.EndUpdate;
|
||
|
ImgView32.Refresh;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.FilpVerticalItemClick(Sender: TObject);
|
||
|
var
|
||
|
x : integer;
|
||
|
y : integer;
|
||
|
DestX : integer;
|
||
|
DestY : integer;
|
||
|
C : TColor32;
|
||
|
begin
|
||
|
AlphaView.Bitmap.Assign(ImgView32.Bitmap);
|
||
|
|
||
|
ImgView32.BeginUpdate;
|
||
|
ImgView32.Bitmap.Width := AlphaView.Bitmap.Width;
|
||
|
ImgView32.Bitmap.Height := AlphaView.Bitmap.Height;
|
||
|
|
||
|
for x := 0 to AlphaView.Bitmap.Width - 1 do
|
||
|
for y := 0 to AlphaView.Bitmap.Height - 1 do
|
||
|
begin
|
||
|
C := AlphaView.Bitmap.Pixel[x, y];
|
||
|
|
||
|
DestX := X;
|
||
|
DestY := (ImgView32.Bitmap.Height - 1) - Y;
|
||
|
|
||
|
ImgView32.Bitmap.Pixels[DestX, DestY] := C;
|
||
|
end;
|
||
|
|
||
|
ImgView32.EndUpdate;
|
||
|
ImgView32.Refresh;
|
||
|
end;
|
||
|
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.FilterTimerTimer(Sender: TObject);
|
||
|
var
|
||
|
Resampler: TKernelResampler;
|
||
|
begin
|
||
|
FilterTimer.Enabled := False;
|
||
|
Resampler := TKernelResampler.Create(ImgView32.Bitmap);
|
||
|
Resampler.Kernel := TSplineKernel.Create;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.ImgView32Scroll(Sender: TObject);
|
||
|
begin
|
||
|
FilterTimer.Enabled := False;
|
||
|
if not (ImgView32.Bitmap.Resampler is TNearestResampler) then
|
||
|
TNearestResampler.Create(ImgView32.Bitmap);
|
||
|
FilterTimer.Enabled := True;
|
||
|
end;
|
||
|
// -----------------------------------------------------------------------------
|
||
|
procedure TMainForm.OpenImageItemClick(Sender: TObject);
|
||
|
begin
|
||
|
if OpenDialog.Execute then
|
||
|
begin
|
||
|
try
|
||
|
Screen.Cursor := crHourGlass;
|
||
|
LoadImage(OpenDialog.FileName);
|
||
|
finally
|
||
|
Screen.Cursor := crDefault;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
end.
|