unit dekompres_window;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  Spin, EditBtn, StdCtrls, FractalImageCompression, IntfGraphics, Math;

type

  KKRecord = record
    RaSize:Word;
    XT:Word;
    YT:Word;
    Transf:Byte;
    ST:Single;
    OT:Single;
  end;
  DKKMatrix   = array of KKRecord;

  { TForm3 }

  TForm3 = class(TForm)
    Button_Dekomprimuj: TButton;
    FileNameEdit1: TFileNameEdit;
    FileNameEdit2: TFileNameEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    SpinEdit1: TSpinEdit;
    SpinEdit2: TSpinEdit;
    procedure Button_DekomprimujClick(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end; 

var
  Form3: TForm3; 

  KompresOutputFile: File of KKRecord;      //Datovy vystup
  OutputImage: TLazIntfImage;   // Obrazky
  ActualIndex: Integer;

  PocetIter,Scale:Integer;
  PathSavePicture, PathOpenCompres: String;

const
  DefaultColor=0;

implementation

{ TForm3 }
{******************************************************************************}
{                              PROCEDURY                                       }//PROCEDURY
{******************************************************************************}

{***********************************************************************COUNTXY}
procedure CountXY(var KompresMatrixIn:DKMatrix;X,Y,Depth:Word);
begin
  if KompresMatrixIn[ActualIndex].RaSize=((KompresMatrixIn[0].XT) div Round(Power(2,Depth))) then
  begin
    KompresMatrixIn[ActualIndex].XR:=X;
    KompresMatrixIn[ActualIndex].YR:=Y;
    ActualIndex:=ActualIndex+1;
  end else
  begin
    CountXY(KompresMatrixIn,X,Y,Depth+1);
    CountXY(KompresMatrixIn,X+KompresMatrixIn[0].XT div Round(Power(2,Depth+1)),
      Y,Depth+1);
    CountXY(KompresMatrixIn,X,Y+KompresMatrixIn[0].XT div
      Round(Power(2,Depth+1)),Depth+1);
    CountXY(KompresMatrixIn,X+KompresMatrixIn[0].XT div Round(Power(2,Depth+1)),
      Y+KompresMatrixIn[0].XT div Round(Power(2,Depth+1)),Depth+1);
  end;
end;
{********************************************************************LOADOUTPUT}
procedure LoadOutput(Path:String);
var i,j,r,g,b: LongInt;
    MKRecord:KKRecord;
begin
  AssignFile(KompresOutputFile, Path);
  Reset(KompresOutputFile);
  KompresMatrix_R:=nil;
  KompresMatrix_G:=nil;
  KompresMatrix_B:=nil;
  i:=0;j:=0;r:=0;g:=0;b:=0;
  While not Eof(KompresOutputFile) do
  begin
    i:=i+1;
    Read(KompresOutputFile,MKRecord);
    if MKRecord.Transf=0 then
    begin
      j:=j+1;
      if j=1 then r:=i;
      if j=2 then g:=i;
      if j=3 then b:=i;
    end;
    if j=1 then
    begin
      SetLength(KompresMatrix_R,i);
      KompresMatrix_R[i-1].RaSize:=MKRecord.RaSize;
      KompresMatrix_R[i-1].XR:=0;
      KompresMatrix_R[i-1].YR:=0;
      KompresMatrix_R[i-1].XT:=MKRecord.XT;
      KompresMatrix_R[i-1].YT:=MKRecord.YT;
      KompresMatrix_R[i-1].Transf:=MKRecord.Transf;
      KompresMatrix_R[i-1].ST:=MKRecord.ST;
      KompresMatrix_R[i-1].OT:=MKRecord.OT;
    end;
    if j=2 then
    begin
      SetLength(KompresMatrix_G,i-g+1);
      KompresMatrix_G[i-g].RaSize:=MKRecord.RaSize;
      KompresMatrix_G[i-g].XR:=0;
      KompresMatrix_G[i-g].YR:=0;
      KompresMatrix_G[i-g].XT:=MKRecord.XT;
      KompresMatrix_G[i-g].YT:=MKRecord.YT;
      KompresMatrix_G[i-g].Transf:=MKRecord.Transf;
      KompresMatrix_G[i-g].ST:=MKRecord.ST;
      KompresMatrix_G[i-g].OT:=MKRecord.OT;
    end;
    if j=3 then
    begin
      SetLength(KompresMatrix_B,i-b+1);
      KompresMatrix_B[i-b].RaSize:=MKRecord.RaSize;
      KompresMatrix_B[i-b].XR:=0;
      KompresMatrix_B[i-b].YR:=0;
      KompresMatrix_B[i-b].XT:=MKRecord.XT;
      KompresMatrix_B[i-b].YT:=MKRecord.YT;
      KompresMatrix_B[i-b].Transf:=MKRecord.Transf;
      KompresMatrix_B[i-b].ST:=MKRecord.ST;
      KompresMatrix_B[i-b].OT:=MKRecord.OT;
    end;
  end;
  CloseFile(KompresOutputFile);
  ActualIndex:=1;
  CountXY(KompresMatrix_R,0,0,0);
  If KompresMatrix_R[0].ST=0 then
  begin
    ActualIndex:=1;
    CountXY(KompresMatrix_G,0,0,0);
    ActualIndex:=1;
    CountXY(KompresMatrix_B,0,0,0);
    BW:=False;
  end else
  begin
    BW:=True;
  end;
end;

procedure TForm3.Button_DekomprimujClick(Sender: TObject);
var i,j: Integer;
    MemTBip:TBitmap;
begin
  PocetIter:=SpinEdit1.Value;
  Scale:=SpinEdit2.Value;
  PathOpenCompres:=FileNameEdit1.FileName;
  PathSavePicture:=FileNameEdit2.FileName;

  LoadOutput(PathOpenCompres);

  MemTBip:=TBitmap.Create;
  OutputImage:=TLazIntfImage.Create(0,0);
  MemTBip.LoadFromLazarusResource('output');
  OutputImage.LoadFromBitmap(MemTBip.Handle,MemTBip.MaskHandle);

  SetLength(MemoryOutputImageMatrix_R, (KompresMatrix_R[0].YT)*Scale);
  SetLength(MemoryOutputImageMatrix_G, (KompresMatrix_R[0].XT)*Scale);
  SetLength(MemoryOutputImageMatrix_B, (KompresMatrix_R[0].XT)*Scale);
  for i:=0 to ((KompresMatrix_R[0].XT)*Scale)-1 do
  begin
    SetLength(MemoryOutputImageMatrix_R[i], (KompresMatrix_R[0].XT)*Scale);
    SetLength(MemoryOutputImageMatrix_G[i], (KompresMatrix_R[0].XT)*Scale);
    SetLength(MemoryOutputImageMatrix_B[i], (KompresMatrix_R[0].XT)*Scale);
  end;

  for i:=0 to High(MemoryOutputImageMatrix_R) do
    for j:=0 to High(MemoryOutputImageMatrix_R) do
      begin
        MemoryOutputImageMatrix_R[i,j]:=DefaultColor;
        MemoryOutputImageMatrix_G[i,j]:=DefaultColor;
        MemoryOutputImageMatrix_B[i,j]:=DefaultColor;
      end;

  DekompresDo(KompresMatrix_R,MemoryOutputImageMatrix_R,Scale,PocetIter);
  if KompresMatrix_R[0].ST = 0 then
  begin
    DekompresDo(KompresMatrix_G,MemoryOutputImageMatrix_G,Scale,PocetIter);
    DekompresDo(KompresMatrix_B,MemoryOutputImageMatrix_B,Scale,PocetIter);
  end else
  begin
    MemoryOutputImageMatrix_G:=MemoryOutputImageMatrix_R;
    MemoryOutputImageMatrix_B:=MemoryOutputImageMatrix_R;
  end;

  OutputImage.SetSize((KompresMatrix_R[0].XT)*Scale,
                      (KompresMatrix_R[0].XT)*Scale);

  for i:= 0 to ((KompresMatrix_R[0].XT*Scale)-1) do
  begin
    for j:= 0 to ((KompresMatrix_R[0].XT*Scale)-1) do
    begin
      OutputImage.Colors[i,j]:=TColorToFPColor(RGBToColor(
                               Max(Min(255,MemoryOutputImageMatrix_R[i,j]),0),
                               Max(Min(255,MemoryOutputImageMatrix_G[i,j]),0),
                               Max(Min(255,MemoryOutputImageMatrix_B[i,j]),0)));
    end;
  end;
  OutputImage.SaveToFile(PathSavePicture);
    ShowMessage('Dekomprese proběhla úspěšně!');
end;

initialization
  {$I dekompres_window.lrs}
  {$I Fraktalni_komprese_resources.lrs}

end.

