{
   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_saveas;

interface

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

type
  TWorkThread = class;

  Tfrmwork_saveas = class(Tfrmworkbase)
    ComboBox1: TComboBox;
    Edit1: TEdit;
    Label2: TLabel;
    Label1: TLabel;
    GroupBox1: TGroupBox;
    CheckBox1: TCheckBox;
    Label11: TLabel;
    SpinEdit1: TSpinEdit;
    Label12: TLabel;
    SpinEdit2: TSpinEdit;
    TypeCombo: TComboBox;
    Label14: TLabel;
    Label13: TLabel;
    Button1: TButton;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure ComboBox1Change(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;
    noanswer:boolean;
    currentfilename:string;

    procedure savefile(data:PThumbImage;dest:string);
    procedure fileexistproc;
  protected
    procedure Execute; override;
  public
    formhandle:thandle;
    list:tlist;
    extselectidx:integer;
    prefix,path:string;
    resize:boolean;
    resize_width,resize_height:integer;
    resize_method:integer;
    convert24bit,removetrans:boolean;
    constructor CreateThread;
    destructor Destroy; override;
  end;

implementation

uses Ufrmmain, Udialog, FreeBitmap, FreeImage, FreeUtils, Ufunction, Uconfig,
  Uexistmsg, Ufrmsaveopt;
{$R *.dfm}

{TWorkThread}
constructor TWorkThread.CreateThread;
begin
  FreeOnTerminate:=false;
  noanswer:=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, path)
       else
         savefile(PThumbImage1, 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(data:PThumbImage;dest:string);
var
  s,ext:string;
  FBitmap:TFreeWinBitmap;
  w,h,NewWidth,NewHeight:integer;
  flag:boolean;
begin
  sendmessage(formhandle, wm_user+1001, list.Count, currentcount);
  s:=format('%d/%d (%s)',[currentcount,list.Count,ExtractFileName(dest)]);
  sendmessage(formhandle, wm_user+1002, integer(pchar(s)), 0);

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

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

    if resize then begin
      w:=FBitmap.GetWidth;
      h:=FBitmap.GetHeight;
      if (resize_width>0) and (resize_height=0) then begin
        NewWidth:=resize_width;
        NewHeight:=Round(NewWidth * h / w);
      end else if (resize_width=0) and (resize_height>0) then begin
        NewHeight:=resize_height;
        NewWidth:=Round(NewHeight * w / h);
      end else if (resize_width>0) and (resize_height>0) then begin
        NewHeight:=resize_height;
        NewWidth:=resize_width;
      end else begin
        NewHeight:=h;
        NewWidth:=w;
      end;
      FBitmap.Rescale(NewWidth,NewHeight,TFreeStretchFilter(self.resize_method));
    end;

    if comparetext(ExtractFileExt(dest),'.gif')=0 then begin
      if FBitmap.IsTransparent then
        FBitmap.SetTransparentBg(nil);
      FBitmap.ConvertTo24Bits;
      FBitmap.ColorQuantize(FIQ_WUQUANT);
    end else begin
      if removetrans and FBitmap.IsTransparent then
        FBitmap.SetTransparentBg(nil);
      if convert24bit and (FBitmap.GetBitsPerPixel>24) then
        FBitmap.ConvertTo24Bits;
    end;

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

end;

{Tfrmwork_saveas}
procedure Tfrmwork_saveas.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;
  self.TypeCombo.ItemIndex:=config.c_resize_method;
  self.Edit1.Text:=config.getvaluebystring('config_saveas_prefix','_new');
  CheckBox2.Checked:=boolean(config.getvaluebyinteger('config_saveas_convert24bit',0));
  CheckBox3.Checked:=boolean(config.getvaluebyinteger('config_saveas_removetrans',0));
  btnok.Caption:='저장';
end;

procedure Tfrmwork_saveas.OkSeleted;
var
  s,ext,path:string;
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.resize:=self.CheckBox1.Checked;
  WorkThread.resize_width:=self.SpinEdit1.Value;
  WorkThread.resize_height:=self.SpinEdit2.Value;
  WorkThread.resize_method:=self.TypeCombo.ItemIndex;
  WorkThread.convert24bit:=CheckBox2.Checked;
  WorkThread.removetrans:=CheckBox3.Checked;
  WorkThread.OnTerminate:=WorkThreadOnTerminate;
  WorkThread.Resume;
end;

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

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

procedure Tfrmwork_saveas.FormDestroy(Sender: TObject);
begin
  config.c_resize_method:=self.TypeCombo.ItemIndex;
  config.c_lastselfiletype:=ComboBox1.ItemIndex;
  config.setvaluebystring('config_saveas_prefix',self.Edit1.Text);
  config.setvaluebyinteger('config_saveas_convert24bit',integer(CheckBox2.Checked));
  config.setvaluebyinteger('config_saveas_removetrans',integer(CheckBox3.Checked));
  inherited;
end;

procedure Tfrmwork_saveas.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_saveas.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_saveas.FormShow(Sender: TObject);
begin
  inherited;
  if list.Count=1 then begin
    comboBox1.Enabled:=false;
    edit1.Enabled:=false;
    Button1.Enabled:=false;
  end;
end;

end.
