{

   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;

type
  TWorkThread = class;

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

    procedure OkSeleted; override;
    procedure CancelSeleted; override;
    procedure WorkThreadOnprogress(Sender:TObject;
      totcount,currentcount:integer; msg:string; iserror:boolean);
    procedure WorkThreadOnTerminate(sender:tobject);
  public
    { Public declarations }
  end;

  TWorkThread = class(TThread)
  private
    totcount,currentcount:integer;
    FOnprogress:TOnprogress;
    ExistMethod:integer;
    currentfilename:string;
    progressmsg:string;    

    procedure savefile(srcfile,filename:string);
    procedure fileexistproc;
    procedure proc_onprogress;
  protected
    procedure Execute; override;
  public
    workselect:tworkselect;
    extselectidx,thumbsize:integer;
    path:string;
    prefix:string;
    constructor CreateThread;
    destructor Destroy; override;
  published
    property Onprogress:TOnprogress read FOnprogress write FOnprogress;
  end;

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

{$R *.dfm}

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

destructor TWorkThread.Destroy;
begin
  inherited Destroy;
end;

function makefilename(name,prefix:string):string;
var
  s,s1:string;
begin
  s:=sysutils.ExtractFileName(name);
  s1:=sysutils.ExtractFileExt(name);
  s:=sysutils.StringReplace(s,s1,'',[rfReplaceAll]);
  result:=s+prefix+s1;
end;

procedure TWorkThread.Execute;
var
  i:integer;
  PThumbImage1:PThumbImage;
begin
try
  case self.workselect of
    wscurrent:begin
      totcount:=1;
      currentcount:=1;
      savefile(currentimage.name,path);
    end;
    wslistselect,wslistall:begin
      for i:=0 to frmmain.listview1.Items.Count-1 do
        if (workselect=wslistall) or (frmmain.listview1.Items[i].Selected) then
          if PThumbImage(frmmain.listview1.Items[i].Data).imagetype<>itfolder then
             inc(totcount);

      currentcount:=0;
      for i:=0 to frmmain.listview1.Items.Count-1 do
        if (workselect=wslistall) or (frmmain.listview1.Items[i].Selected) then begin
          if self.Terminated then exit;
          PThumbImage1:=PThumbImage(frmmain.listview1.Items[i].Data);
          if PThumbImage1.imagetype=itfolder then continue;
          inc(currentcount);
          savefile(PThumbImage1.name,path+makefilename(PThumbImage1.name,prefix));
        end;
    end;
  end;
except
    on E: Exception do begin
      progressmsg:=E.Message;
      Synchronize(proc_onprogress);
    end;
end;
end;

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

procedure TWorkThread.savefile(srcfile,filename:string);
var
  s:string;
  FBitmap:TFreeWinBitmap;
  NewWidth,NewHeight: Integer;
  w,h:integer;
  FreeMemoryIO1:TFreeMemoryIO;
  stream:tmemorystream;
  flag:boolean;
begin
  if workselect<>wscurrent then begin
    s:=FIU_GetSelectExt(extselectidx+1);
    filename:=sysutils.ChangeFileExt(filename,s);
  end;

  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;
  end;

  FBitmap:=TFreeWinBitmap.Create;
  stream:=tmemorystream.Create;
  try
    if workselect=wscurrent then begin
      frmmain.imgview321.Bitmap.SaveToStream(stream);
      FreeMemoryIO1:=TFreeMemoryIO.Create(stream.Memory,stream.Size);
      try
        if FBitmap.LoadFromMemory(FreeMemoryIO1)=false then begin
          progressmsg:=format('%s 파일을 읽을수 없습니다.',[ExtractFileName(srcfile)]);
          Synchronize(proc_onprogress);
          exit;
        end;
      finally
        FreeMemoryIO1.Free;
      end;
    end else begin
      if FBitmap.Load(srcfile)=false then begin
        progressmsg:=format('%s 파일을 읽을수 없습니다.',[ExtractFileName(srcfile)]);
        Synchronize(proc_onprogress);
        exit;
      end;
    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
      progressmsg:=format('%s 저장에 실패했습니다.',[ExtractFileName(filename)]);
      Synchronize(proc_onprogress);
      exit;
    end;
  finally
    FBitmap.Free;
    stream.Free;
  end;

  progressmsg:=ExtractFileName(filename);
  Synchronize(proc_onprogress);
end;

procedure TWorkThread.proc_onprogress;
begin
  if assigned(FOnprogress) then
    FOnprogress(self,totcount,currentcount,progressmsg,false);
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.ItemIndex:=config.c_lastthumbsize;
end;

procedure Tfrmwork_thumb.OkSeleted;
var
  s,path:string;
  i,count:integer;
  PThumbImage1:PThumbImage;
  flag:boolean;
begin
try
  flag:=false;
  case self.workselect of
    wscurrent:begin
      if currentimage.name='' then begin
        MessageDlg('현재 그림/사진이 없습니다.',mterror, [mbOk], 0);
        exit;
      end;
    end;
    wslistselect,wslistall:begin
      count:=0;
      for i:=0 to frmmain.listview1.Items.Count-1 do
        if (workselect=wslistall) or (frmmain.listview1.Items[i].Selected) then begin
          PThumbImage1:=PThumbImage(frmmain.listview1.Items[i].Data);
          if PThumbImage1.imagetype<>itfolder then begin
            inc(count);
            if count=1 then
              path:=sysutils.ExtractFilePath(PThumbImage1.name);
          end;
        end;
      if count=0 then begin
        MessageDlg('생성할 그림/사진이 없습니다.',mterror, [mbOk], 0);
        exit;
      end;
    end;
  end;

  if workselect=wscurrent then begin

    SaveDialog1.Filter:=ComboBox1.Items[ComboBox1.ItemIndex];
    SaveDialog1.FilterIndex:=0;

    if config.c_uselastdir then
      SaveDialog1.InitialDir:=config.lastdir
    else
      SaveDialog1.InitialDir:=ExtractFilePath(currentimage.name);
    s:=ChangeFileExt(makefilename(currentimage.name,edit1.Text),
       FIU_GetSelectExt(ComboBox1.ItemIndex+1));
    SaveDialog1.FileName:=ExtractFileName(s);

    if SaveDialog1.Execute=false then exit;

    s:=sysutils.ChangeFileExt(
      SaveDialog1.FileName,
      FIU_GetSelectExt(ComboBox1.ItemIndex+1));
    path:=s;
    config.lastdir:=sysutils.ExtractFilePath(SaveDialog1.FileName);

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

    if path[length(path)]<>'\' then path:=path+'\';
    config.lastdir:=path;

  end;

  flag:=true;
finally
  if flag=false then btnok.Enabled:=true;
end;

  selectsaveflag:=get_reg_saveopt_flag(FIU_GetFIFType2(FIU_GetSelectExt(ComboBox1.ItemIndex+1)),false);
  config.c_lastselfiletype:=ComboBox1.ItemIndex;
  config.c_lastthumbsize:=ComboBox2.ItemIndex;

  WorkThread:=TWorkThread.CreateThread;
  WorkThread.workselect:=self.workselect;
  WorkThread.extselectidx:=combobox1.ItemIndex;
  WorkThread.path:=path;
  WorkThread.prefix:=edit1.Text;
  WorkThread.Onprogress:=WorkThreadOnprogress;
  WorkThread.OnTerminate:=WorkThreadOnTerminate;
  WorkThread.thumbsize:=strtointdef(combobox2.Items[config.c_lastthumbsize],100);
  WorkThread.Resume;
end;

procedure Tfrmwork_thumb.WorkThreadOnTerminate(sender:tobject);
begin
  labelcomplete.Visible:=true;
  self.btncancel.Caption:='닫기';
  btncancel.SetFocus;
end;

procedure Tfrmwork_thumb.WorkThreadOnprogress(Sender:TObject;
  totcount,currentcount:integer; msg:string; iserror:boolean);
begin
  ProgressBar1.Max:=totcount;
  ProgressBar1.Position:=currentcount;
  label3.Caption:=format('%d/%d [%s]',[currentcount,totcount,msg]);
  if iserror then
    MessageDlg(msg,mtError, [mbOk], 0);
end;

procedure Tfrmwork_thumb.CancelSeleted;
begin
  if WorkThread=nil then exit;
  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;

end.
