{

   This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either
  version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
}
unit Ufrmwork_thumb;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Buttons, ComCtrls, Ufrmworkbase, Mask, Spin;

type
  TWorkThread = class;

  Tfrmwork_thumb = class(Tfrmworkbase)
    ComboBox1: TComboBox;
    Edit1: TEdit;
    Label2: TLabel;
    Label1: TLabel;
    ComboBox2: TComboBox;
    Label4: TLabel;
    Button1: TButton;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ComboBox2Exit(Sender: TObject);
    procedure FormShow(Sender: TObject);
  private
    { Private declarations }
    WorkThread:TWorkThread;

    procedure OkSeleted; override;
    function CancelSeleted:boolean; override;
    procedure WorkThreadOnTerminate(sender:tobject);
  public
    { Public declarations }
  end;

  TWorkThread = class(TThread)
  private
    currentcount:integer;
    ExistMethod:integer;
    currentfilename:string;

    procedure savefile(srcfile,filename:string);
    procedure fileexistproc;
  protected
    procedure Execute; override;
  public
    formhandle:thandle;
    list:tlist;
    extselectidx,thumbsize:integer;
    path:string;
    prefix:string;
    constructor CreateThread;
    destructor Destroy; override;
  end;

implementation
uses FreeBitmap, FreeImage, FreeUtils, Uconfig,
  Ufunction, UfrmMain, Udialog, Uexistmsg, UBrowserListView, Ufrmsaveopt;

{$R *.dfm}

{TWorkThread}
constructor TWorkThread.CreateThread;
begin
  FreeOnTerminate:=false;
  currentcount:=0;
  inherited Create(true);
end;

destructor TWorkThread.Destroy;
begin
  inherited Destroy;
end;

procedure TWorkThread.Execute;
var
  i:integer;
  PThumbImage1:PThumbImage;
  s:string;
begin
  try
     if list.Count=1 then
       s:=format('"%s" 파일로 저장중...',[path])
     else begin
       s:=path;
       if (length(s)>0) and (s[length(s)]='\') then delete(s,length(s),1);
       s:=format('"%s" 폴더에 저장중...',[s]);
     end;
     sendmessage(formhandle, wm_user+1003, integer(pchar(s)), 0);

     for i:=0 to list.Count-1 do begin
       if self.Terminated then break;
       PThumbImage1:=PThumbImage(list.Items[i]);
       inc(currentcount);
       if list.Count=1 then
         savefile(PThumbImage1.name, path)
       else
         savefile(PThumbImage1.name, path+makefilename(PThumbImage1.name,prefix));
     end;
  except
    on E: Exception do begin
      sendmessage(formhandle, wm_user+1003, integer(pchar(E.Message)), 0);
    end;
  end;

  s:='완료되었습니다.';
  sendmessage(formhandle, wm_user+1003, integer(pchar(s)), 0);
end;

procedure TWorkThread.fileexistproc;
var
  frmExistMsg:TfrmExistMsg;
begin
  frmExistMsg:=TfrmExistMsg.Create(frmworkbase);
  try
    frmExistMsg.Label1.Caption:=
     format('"%s" 파일이 존재합니다.',[ExtractFileName(currentfilename)]);
    frmExistMsg.ShowModal;
  finally
    frmExistMsg.Free;
  end;
end;

procedure TWorkThread.savefile(srcfile,filename:string);
var
  s,ext:string;
  FBitmap:TFreeWinBitmap;
  NewWidth,NewHeight: Integer;
  w,h:integer;
  flag:boolean;
begin
  sendmessage(formhandle, wm_user+1001, list.Count, currentcount);
  s:=format('%d/%d (%s)',[currentcount,list.Count,ExtractFileName(filename)]);
  sendmessage(formhandle, wm_user+1002, integer(pchar(s)), 0);

  if (list.Count>1) then begin
    ext:=FIU_GetSelectExt(extselectidx+1);
    filename:=sysutils.ChangeFileExt(filename,ext);
    if sysutils.FileExists(filename) then begin
      currentfilename:=filename;
      if existnoanswer=false then
         self.Synchronize(fileexistproc);
      case config.c_existmethod of
        0:filename:=makeuniqfilename(filename);
        1:exit;
      end;
      s:=format('%d/%d (%s)',[currentcount,list.Count,ExtractFileName(filename)]);
      sendmessage(formhandle, wm_user+1002, integer(pchar(s)), 0);
    end;
  end;

  FBitmap:=TFreeWinBitmap.Create;
  try
    if FBitmap.Load(srcfile)=false then begin
      s:=format('%s 파일을 읽을수 없습니다.',[ExtractFileName(srcfile)]);
      sendmessage(formhandle, wm_user+1003, integer(pchar(s)), 0);
      exit;
    end;

    if FBitmap.IsTransparent then
      FBitmap.SetTransparentBg(nil);

    w:=FBitmap.GetWidth;
    h:=FBitmap.GetHeight;
    if w > h then begin
      NewWidth:=thumbsize;
      NewHeight:=Round(thumbsize * h / w);
    end else begin
      NewWidth:=Round(thumbsize * w / h);
      NewHeight:=thumbsize;
    end;
    if NewWidth > w then NewWidth:=w;
    if NewHeight > h then NewHeight:=h;
    if NewWidth<=0 then NewWidth:=1;
    if NewHeight<=0 then NewHeight:=1;

    FBitmap.MakeThumbnail(NewWidth,NewHeight,FBitmap,config.thumbSharpen,thumbsize);

    if comparetext(ExtractFileExt(filename),'.gif')=0 then begin
      FBitmap.ConvertTo24Bits;
      FBitmap.ColorQuantize(FIQ_WUQUANT);
    end;

    flag:=FBitmap.Save(filename,selectsaveflag);
    if flag=false then begin
      if FBitmap.IsTransparent then
        FBitmap.SetTransparentBg(nil);
      FBitmap.ConvertTo24Bits;
      flag:=FBitmap.Save(filename,selectsaveflag);
    end;
    if flag=false then begin
      s:=format('%s 저장에 실패했습니다.',[ExtractFileName(filename)]);
      sendmessage(formhandle, wm_user+1003, integer(pchar(s)), 0);
      exit;
    end;
  finally
    FBitmap.Free;
  end;
end;

{Tfrmwork_thumb}
procedure Tfrmwork_thumb.FormCreate(Sender: TObject);
var
  strlist:tstringlist;
  i:integer;
begin
  inherited;
  strlist:=tstringlist.Create;
  try
    SplitString(FIU_GetAllFilters3,strlist,'^');
    for i:=0 to strlist.Count-1 do begin
      ComboBox1.Items.Add(strlist.Strings[i])
    end;
    if ComboBox1.Items.Count>config.c_lastselfiletype then
      ComboBox1.ItemIndex:=config.c_lastselfiletype;
    ComboBox1Change(nil);
  finally
    strlist.Free;
  end;

  ComboBox2.Text:=config.getvaluebystring('config_thumb_size','90');
  self.Edit1.Text:=config.getvaluebystring('config_thumb_prefix','_thumb');
  btnok.Caption:='저장';  
end;

procedure Tfrmwork_thumb.OkSeleted;
var
  s,ext,path:string;
  i,count:integer;
label reopendialog;
begin
  if list.Count>1 then begin
    path:=sysutils.ExtractFilePath(PThumbImage(list.items[0]).name);
    edit1.Text:=sysutils.StringReplace(edit1.Text,'.','',[rfReplaceAll]);
    edit1.Text:=deletebadfilenamechar(edit1.Text);

    if config.c_uselastdir then
      path:=config.lastdir;
    if AdvSelectDirectory(handle,'저장할 폴더선택', '', Path, true, False, True)=false then exit;

    if path[length(path)]<>'\' then path:=path+'\';
    config.lastdir:=path;
    selectsaveflag:=get_reg_saveopt_flag(FIU_GetFIFType2(FIU_GetSelectExt(ComboBox1.ItemIndex+1)),false);

  end else begin
    if lastfilename<>'' then
      s:=lastfilename
    else
      s:=PThumbImage(list.items[0]).name;

    SaveDialog1.Filter:=FIU_GetAllFilters2;
    SaveDialog1.FilterIndex:=FIU_GetSelectidx(lowercase(ExtractFileExt(s)));;

    if config.c_uselastdir then
      SaveDialog1.InitialDir:=config.lastdir
    else
      SaveDialog1.InitialDir:=ExtractFilePath(s);
    SaveDialog1.FileName:=ChangeFileExt(ExtractFileName(s),'');
    SaveDialog1.enablesaveopt:=true;

reopendialog:
    if SaveDialog1.Execute=false then exit;

    ext:=FIU_GetSelectExt(SaveDialog1.FilterIndex);
    selectsaveflag:=get_reg_saveopt_flag(FIU_GetFIFType2(ext),false);

    if pos(lowercase('*'+ExtractFileExt(SaveDialog1.FileName)+';'),
         lowercase(FIU_GetSelectExtfull(SaveDialog1.FilterIndex)))=0 then
      s:=sysutils.ChangeFileExt(SaveDialog1.FileName,ext)
    else
      s:=SaveDialog1.FileName;
    config.lastdir:=sysutils.ExtractFilePath(s);

    if sysutils.FileExists(s) then begin
      if MessageDlg(format('"%s" 파일이 이미 존재합니다.',[ExtractFileName(s)])+#13#10+'덮어 씌우시겠습니까?',
           mtConfirmation, [mbYes, mbNo], 0)<>mrYes then
       goto reopendialog;
    end;

    lastfilename:=s;
    path:=s;
  end;

  existnoanswer:=false;
  btnok.Enabled:=false;
  self.btncancel.Caption:='취소';

  WorkThread:=TWorkThread.CreateThread;
  WorkThread.formhandle:=handle;
  WorkThread.list:=list;
  WorkThread.extselectidx:=combobox1.ItemIndex;
  WorkThread.path:=path;
  WorkThread.prefix:=edit1.Text;
  WorkThread.OnTerminate:=WorkThreadOnTerminate;
  WorkThread.thumbsize:=strtointdef(combobox2.Text,90);
  WorkThread.Resume;
end;

procedure Tfrmwork_thumb.WorkThreadOnTerminate(sender:tobject);
begin
  WorkThread:=nil;
  self.btncancel.Caption:='닫기';
  btnok.Enabled:=true;
  btncancel.SetFocus;
end;

function Tfrmwork_thumb.CancelSeleted:boolean;
begin
  result:=true;
  if WorkThread=nil then exit;
  result:=false;
  WorkThread.Terminate;
  WorkThread.WaitFor;
  WorkThread.Free;
end;

procedure Tfrmwork_thumb.Button1Click(Sender: TObject);
begin
  frmsaveopt:=Tfrmsaveopt.Create(self);
  try
    frmsaveopt.selectformat:=Button1.Tag;
    if frmsaveopt.ShowModal=mrok then ;
  finally
    frmsaveopt.Free;
  end;
end;

procedure Tfrmwork_thumb.ComboBox1Change(Sender: TObject);
var
  f:FREE_IMAGE_FORMAT;
begin
  f:=FIU_GetFIFType2(FIU_GetSelectExt(ComboBox1.ItemIndex+1));
  case f of
    FIF_BMP,FIF_JPEG,FIF_PNG,FIF_TIFF:
      Button1.Enabled:=true;
    else
      Button1.Enabled:=false;
  end;
  Button1.Tag:=f;
end;

procedure Tfrmwork_thumb.FormDestroy(Sender: TObject);
begin
  config.c_lastselfiletype:=ComboBox1.ItemIndex;
  config.setvaluebystring('config_thumb_size',ComboBox2.Text);
  config.setvaluebystring('config_thumb_prefix',self.Edit1.Text);
  inherited;
end;

procedure Tfrmwork_thumb.ComboBox2Exit(Sender: TObject);
var
  v:integer;
begin
  if TryStrToInt(combobox2.Text,v)=false then
    combobox2.Text:='90'
  else begin
    if (v<30) or (v>1000) then
      combobox2.Text:='90';
  end;
end;

procedure Tfrmwork_thumb.FormShow(Sender: TObject);
begin
  inherited;
  if list.Count=1 then begin
    comboBox1.Enabled:=false;
    edit1.Enabled:=false;
    Button1.Enabled:=false;
  end;
end;

end.
