{

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

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, UfrmEffectBase, UBrowserListView, ComCtrls, StdCtrls, ExtCtrls, GR32,
  gr32_transforms, GR32_Resamplers;

type
  TfrmEffect_Album = class(TfrmEffectBase)
    Panel3: TPanel;
    Label1: TLabel;
    ScaleCombo: TComboBox;
    CheckBox1: TCheckBox;
    ListView1: TListView;
    Splitter1: TSplitter;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ListView1DblClick(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure Splitter1Moved(Sender: TObject);
  private
    { Private declarations }
    BrowserListView1:TBrowserListView;
    procedure AlbumGenerate(PThumbImage1:PThumbImage; dest:tbitmap32);
    procedure ok_select; override;
    procedure imageprocess(var src:tbitmap);
  public
    { Public declarations }
  end;

var
  frmEffect_Album: TfrmEffect_Album;

implementation

uses Uconfig, Ufrmmain, inifiles, Ufunction;
{$R *.dfm}

procedure TfrmEffect_Album.FormCreate(Sender: TObject);
begin
  inherited;
  PanelPreView.Align:=alClient;
  imagepreview1.ScrollBars.Size:=0;

  self.BorderStyle:=bsSizeable;
  self.BorderIcons:=[biSystemMenu,biMaximize];
  if config.effect_width>=0 then self.Width:=config.effect_width
  else self.Width:=750;
  if config.effect_height>=0 then self.Height:=config.effect_height
  else self.Height:=500;
  if config.effect_max then WindowState:=wsMaximized;

  BrowserListView1:=TBrowserListView.Create(ListView1,60);
  BrowserListView1.TextOutStyle:=tosNoDesc;
  BrowserListView1.TextNameShort:=true;
  BrowserListView1.Setthumbspace(22);
  BrowserListView1.BrowserDirectory(GetAppDirectory+'album');
end;

procedure TfrmEffect_Album.FormShow(Sender: TObject);
begin
  inherited;
  applyselect.Visible:=true;

  self.setScaleCombo(ScaleCombo);

  self.CheckBox1.Checked:=boolean(config.getvaluebyinteger('album_srcsizeretain',1));
  ListView1.Width:=config.getvaluebyinteger('album_listview1width',144);
  ListView1.Arrange(arAlignTop);
end;

procedure TfrmEffect_Album.FormDestroy(Sender: TObject);
begin
  inherited;
  BrowserListView1.Free;
  config.effect_max:=WindowState=wsMaximized;
  config.setvaluebyinteger('scaleindex',ScaleCombo.ItemIndex);
  config.setvaluebyinteger('album_srcsizeretain',integer(self.CheckBox1.Checked));
  config.setvaluebyinteger('album_listview1width',self.ListView1.Width);

  if WindowState=wsnormal then begin
    config.effect_width:=self.Width;
    config.effect_height:=self.Height;
  end;  
end;

procedure TfrmEffect_Album.ListView1DblClick(Sender: TObject);
var
  PThumbImage1:PThumbImage;
begin
  if ListView1.Selected=nil then exit;
  screen.Cursor:=crHourglass;
  try
    PThumbImage1:=ListView1.Selected.Data;
    AlbumGenerate(PThumbImage1,imagepreview1.Bitmap);
  finally
    screen.Cursor:=crdefault;  
  end;
end;

 function stringtopoint(s:string;var point:TPoint):boolean;
 var
   p1:integer;
   s1:string;
 begin
   result:=false;
   p1:=pos(',',s);
   if p1<=0 then exit;
   try
     s1:=trim(copy(s,1,p1-1));
     point.X:=strtoint(s1);
     s1:=trim(copy(s,p1+1,length(s)));
     point.Y:=strtoint(s1);
     result:=true;
   except
   end;
 end;

procedure TfrmEffect_Album.AlbumGenerate(PThumbImage1:PThumbImage; dest:tbitmap32);
var
  bmpfilename,inifilename:string;
  Ini:TInifile;
  value:string;

  TopLeft,TopRight,BottomLeft,BottomRight:TPoint;
  StartPoint,EndPoint:TPoint;
  stretch:boolean;

  i,j:integer;
  bitmap1,BitmapAlbum,bitmap2:TBitmap32;
  w,h,w1,h1:integer;
  destrect,srcrect:TRect;
  stretchsize:integer;
  repeatsize:integer;
  resampler:TCustomResampler;
begin
  bmpfilename:=PThumbImage1.name;
  inifilename:=sysutils.ChangeFileExt(bmpfilename,'.ini');
  Ini:=TInifile.Create(inifilename);
  value:=ini.ReadString('Information','TopLeft','');
  if stringtopoint(value,TopLeft)=false then exit;
  value:=ini.ReadString('Information','TopRight','');
  if stringtopoint(value,TopRight)=false then exit;
  value:=ini.ReadString('Information','BottomLeft','');
  if stringtopoint(value,BottomLeft)=false then exit;
  value:=ini.ReadString('Information','BottomRight','');
  if stringtopoint(value,BottomRight)=false then exit;
  value:=ini.ReadString('Information','StartPoint','');
  if stringtopoint(value,StartPoint)=false then exit;
  value:=ini.ReadString('Information','EndPoint','');
  if stringtopoint(value,EndPoint)=false then exit;

  value:=ini.ReadString('Information','BorderType','');
  if value='Repeat' then stretch:=false
  else stretch:=true;
  stretchsize:=2;
  ini.Free;

  bitmap1:=TBitmap32.Create;
  bitmap2:=TBitmap32.Create;
  w:=org_bitmap32.Width;
  h:=org_bitmap32.Height;

  //load album
  BitmapAlbum:=TBitmap32.Create;
  BitmapAlbum.LoadFromFile(bmpfilename);

  w1:=BitmapAlbum.Width;
  h1:=BitmapAlbum.Height;

  if self.CheckBox1.Checked then begin
    w:=w+StartPoint.X+(w1-EndPoint.X);
    h:=h+StartPoint.Y+(h1-EndPoint.Y);
  end;
  bitmap1.SetSize(w,h);

  if stretch then begin

    //top stretch
    destrect:=rect(TopLeft.X,0,w-(w1-TopRight.X),TopLeft.Y);
    srcrect:=rect(TopLeft.X,0,TopLeft.X+stretchsize,TopLeft.Y);
    bitmap1.Draw(destrect,srcrect,BitmapAlbum);
    //bottom stretch
    destrect:=rect(BottomLeft.X, h-(h1-BottomLeft.Y), w-(w1-BottomRight.X), h);
    srcrect:=rect(BottomLeft.X, BottomLeft.Y, BottomLeft.X+stretchsize, h1);
    bitmap1.Draw(destrect,srcrect,BitmapAlbum);
    //left stretch
    destrect:=rect(0, TopLeft.Y, TopLeft.X, h-(h1-BottomLeft.Y));
    srcrect:=rect(0, TopLeft.Y, TopLeft.X, TopLeft.Y+stretchsize);
    bitmap1.Draw(destrect,srcrect,BitmapAlbum);
    //right stretch
    destrect:=rect(w-(w1-TopRight.X), TopRight.Y, w, h-(h1-BottomRight.Y));
    srcrect:=rect(TopRight.X, TopRight.Y, w1, TopRight.Y+stretchsize);
    bitmap1.Draw(destrect,srcrect,BitmapAlbum);

  end else begin
    //top repeat
    repeatsize:=TopRight.X-TopLeft.X;
    j:=(w div repeatsize);
    for i:=0 to j do begin
      destrect:=rect(TopLeft.X+(i*repeatsize), 0, TopLeft.X+(i*repeatsize)+repeatsize, TopLeft.Y);
      srcrect:=rect(TopLeft.X, 0, TopLeft.X+repeatsize, TopLeft.Y);
      bitmap1.Draw(destrect,srcrect,BitmapAlbum);
    end;
    //left repeat
    repeatsize:=BottomRight.Y-TopLeft.Y;
    j:=(h div repeatsize);
    for i:=0 to j do begin
      destrect:=rect(0, TopLeft.Y+(i*repeatsize), TopLeft.X, TopLeft.Y+(i*repeatsize)+repeatsize);
      srcrect:=rect(0, TopLeft.Y, TopLeft.X, TopLeft.Y+repeatsize);
      bitmap1.Draw(destrect,srcrect,BitmapAlbum);
    end;
    //bottom repeat
    repeatsize:=BottomRight.X-BottomLeft.X;
    j:=(w div repeatsize);
    for i:=0 to j do begin
      destrect:=rect(BottomLeft.X+(i*repeatsize), h-(h1-BottomLeft.Y),
        BottomLeft.X+(i*repeatsize)+repeatsize, h);
      srcrect:=rect(BottomLeft.X, BottomLeft.Y, BottomLeft.X+repeatsize, h1);
      bitmap1.Draw(destrect,srcrect,BitmapAlbum);
    end;
    //right repeat
    repeatsize:=BottomRight.Y-TopRight.Y;
    j:=(h div repeatsize);
    for i:=0 to j do begin
      destrect:=rect(w-(w1-TopRight.X), TopRight.Y+(i*repeatsize),
         w, TopRight.Y+(i*repeatsize)+repeatsize);
      srcrect:=rect(TopRight.X, TopRight.Y, w1, TopRight.Y+repeatsize);
      bitmap1.Draw(destrect,srcrect,BitmapAlbum);
    end;
  end;

  //TopLeft
  destrect:=rect(0,0,TopLeft.X,TopLeft.Y);
  srcrect:=rect(0,0,TopLeft.X,TopLeft.Y);
  bitmap1.Draw(destrect,srcrect,BitmapAlbum);
  //TopRight
  destrect:=rect(w-(w1-TopRight.X), 0, w, TopRight.Y);
  srcrect:=rect(TopRight.X, 0, w1, TopRight.Y);
  bitmap1.Draw(destrect,srcrect,BitmapAlbum);
  //BottomLeft
  destrect:=rect(0, h-(h1-BottomLeft.Y), BottomLeft.X, h);
  srcrect:=rect(0, BottomLeft.Y, BottomLeft.X, h1);
  bitmap1.Draw(destrect,srcrect,BitmapAlbum);
  //BottomRight
  destrect:=rect(w-(w1-BottomRight.X), h-(h1-BottomRight.Y), w, h);
  srcrect:=rect(BottomRight.X, BottomRight.Y, w1, h1);
  bitmap1.Draw(destrect,srcrect,BitmapAlbum);

  destrect:=rect(StartPoint.X, StartPoint.Y, w-(w1-EndPoint.X), h-(h1-EndPoint.Y));
  srcrect:=rect(0, 0, org_bitmap32.Width, org_bitmap32.Height);

  if self.CheckBox1.Checked then
    bitmap1.Draw(destrect,srcrect,org_bitmap32)
  else begin
    resampler:=TKernelResampler.Create;
    (resampler as TKernelResampler).Kernel := TLanczosKernel.Create;
    try
      StretchTransfer(bitmap1, destrect, destrect, org_bitmap32, srcrect, resampler, dmCustom, nil);
    finally
      resampler.Free;
    end;
  end;

  dest.Assign(bitmap1);

  BitmapAlbum.Free;
  bitmap1.Free;
  bitmap2.Free;
end;

procedure TfrmEffect_Album.ok_select;
begin
  if applyselect.ItemIndex=0 then
    exit;
    
  frmmain.apply_listimages(applyselect.ItemIndex=1,imageprocess,etAlbum,self.Caption);
  self.ModalResult:=mrcancel;
end;

procedure TfrmEffect_Album.imageprocess(var src:tbitmap);
var
  PThumbImage1:PThumbImage;
begin
  org_bitmap32.Assign(src);
  PThumbImage1:=ListView1.Selected.Data;
  AlbumGenerate(PThumbImage1,org_bitmap32);
  org_bitmap32.AssignTo24(src);
end;

procedure TfrmEffect_Album.Splitter1Moved(Sender: TObject);
begin
  ListView1.Arrange(arAlignTop);
end;

end.
