unit WinForm;
{*=====================================================================
  Classes:   LZRW1/KH De/Compressor

  File:      WinFom.pas

  Summary:
       LZRW1/KH De/Compressor is a very simple, but working
       demo-application to use the Delphi.NET implementation of the
       Kurt HAENEN's LZRW1/KH algoritm. This implementation was
       made by me (Endre I. Simay) and it is in the LZRW1_EIS.pas
       as a compressor-class for it. This implementation also use BitWise
       (bitwiseclass.pas).

       LZRW1 algoritm was interpreted as an extremely fast data compression one
       by Ross N. Williams. The LZRW1KH variant is fast and easy working
       compressing algoritm, which was published by Kurt HAENEN.
       I have the oldest C source from 1991 of it, too.

       Later Kurt HAENEN also published an updated version for Turbo Pascal,
       too. This Pascal version was modified for working securely and with
       Delphi.VCL by Danny Heijl. His code was applied for Herbert J.Beemster's
       UBitmap, which was the base of my TUniBitmap component. The LZRW1KH.pas
       was slightly modified for using in Kylix environment by me.

       The present Delphi.NET implementation is based on experiences with codes,
       while the core of the algoritm remained. That's why the decompressing
       resulted the same uncompressed file even the binary result of compressing
       a file might be different with this class and with the latest VCL-based
       Object Pascal implementation of Delphi version. So, the compression and
       decompression with this Class are crossuseable with its PAS
       (as many as I could implement under .NET). Even with
       LZRSave... and LZRLoad... methods of the mentioned TUniBitmap.

       This implementation also use BitWise (bitwiseclass.pas).

       In this demoapplication you could see sample to use the compression as
       well as some file-handling possibilities (e.g. FileInfo). On other hand
       you could make many improvements, especially in the Error-handligns
       (e.g. you will see the empty else and except).

---------------------------------------------------------------------

  This file is submitted by:

	 endresy@axelero.hu
	 Endre I. Simay,
	 Hungary

THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
=====================================================================*}


interface

uses
  System.Drawing, System.Collections, System.ComponentModel,
  System.Windows.Forms, System.Data,
  System.IO,
  bitwiseclass,
  LZRW1_EIS
  ;

type
  int = integer;

type
  TWinForm = class(System.Windows.Forms.Form)
  {$REGION 'Designer Managed Code'}
  strict private
    /// <summary>
    /// Required designer variable.
    /// </summary>
    Components: System.ComponentModel.Container;
    btnCompress: System.Windows.Forms.Button;
    btnDeCompress: System.Windows.Forms.Button;
    textInput: System.Windows.Forms.TextBox;
    textOutput: System.Windows.Forms.TextBox;
    lblInput: System.Windows.Forms.Label;
    lblOutput: System.Windows.Forms.Label;
    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    procedure InitializeComponent;
    procedure btnCompress_Click(sender: System.Object; e: System.EventArgs);
    procedure btnDeCompress_Click(sender: System.Object; e: System.EventArgs);
    procedure TWinForm_Load(sender: System.Object; e: System.EventArgs);
  {$ENDREGION}
  strict protected
    /// <summary>
    /// Clean up any resources being used.
    /// </summary>
    procedure Dispose(Disposing: Boolean); override;
  public
		compressor : LZRW1KHCompressor;
    constructor Create;
  private
    procedure LZRWCompressFileToStream (InStream:Stream; OutStream:BinaryWriter);
		function LZRWDeCompressFromStream(InStream:BinaryReader):MemoryStream;
  end;

implementation

uses
  System.Globalization;

{$REGION 'Windows Form Designer generated code'}
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
procedure TWinForm.InitializeComponent;
begin
  Self.btnCompress := System.Windows.Forms.Button.Create;
  Self.btnDeCompress := System.Windows.Forms.Button.Create;
  Self.textInput := System.Windows.Forms.TextBox.Create;
  Self.textOutput := System.Windows.Forms.TextBox.Create;
  Self.lblInput := System.Windows.Forms.Label.Create;
  Self.lblOutput := System.Windows.Forms.Label.Create;
  Self.SuspendLayout;
  // 
  // btnCompress
  // 
  Self.btnCompress.Location := System.Drawing.Point.Create(384, 16);
  Self.btnCompress.Name := 'btnCompress';
  Self.btnCompress.Size := System.Drawing.Size.Create(80, 23);
  Self.btnCompress.TabIndex := 0;
  Self.btnCompress.Text := 'Compress';
  Include(Self.btnCompress.Click, Self.btnCompress_Click);
  // 
  // btnDeCompress
  // 
  Self.btnDeCompress.Location := System.Drawing.Point.Create(384, 48);
  Self.btnDeCompress.Name := 'btnDeCompress';
  Self.btnDeCompress.Size := System.Drawing.Size.Create(80, 23);
  Self.btnDeCompress.TabIndex := 1;
  Self.btnDeCompress.Text := 'DeCompress';
  Include(Self.btnDeCompress.Click, Self.btnDeCompress_Click);
  // 
  // textInput
  // 
  Self.textInput.Location := System.Drawing.Point.Create(128, 16);
  Self.textInput.Name := 'textInput';
  Self.textInput.Size := System.Drawing.Size.Create(248, 20);
  Self.textInput.TabIndex := 2;
  Self.textInput.Text := '';
  // 
  // textOutput
  // 
  Self.textOutput.Location := System.Drawing.Point.Create(128, 48);
  Self.textOutput.Name := 'textOutput';
  Self.textOutput.Size := System.Drawing.Size.Create(248, 20);
  Self.textOutput.TabIndex := 3;
  Self.textOutput.Text := '';
  // 
  // lblInput
  // 
  Self.lblInput.Location := System.Drawing.Point.Create(8, 16);
  Self.lblInput.Name := 'lblInput';
  Self.lblInput.Size := System.Drawing.Size.Create(104, 16);
  Self.lblInput.TabIndex := 4;
  Self.lblInput.Text := 'Full Path of Input:';
  // 
  // lblOutput
  // 
  Self.lblOutput.Location := System.Drawing.Point.Create(8, 48);
  Self.lblOutput.Name := 'lblOutput';
  Self.lblOutput.Size := System.Drawing.Size.Create(104, 16);
  Self.lblOutput.TabIndex := 5;
  Self.lblOutput.Text := 'Full Path of Output:';
  // 
  // TWinForm
  // 
  Self.AutoScaleBaseSize := System.Drawing.Size.Create(5, 13);
  Self.ClientSize := System.Drawing.Size.Create(472, 86);
  Self.Controls.Add(Self.lblInput);
  Self.Controls.Add(Self.lblOutput);
  Self.Controls.Add(Self.textInput);
  Self.Controls.Add(Self.textOutput);
  Self.Controls.Add(Self.btnCompress);
  Self.Controls.Add(Self.btnDeCompress);
  Self.Name := 'TWinForm';
  Self.Text := 'LZRW1/KH De/Compressor by E.I. Simay';
  Include(Self.Load, Self.TWinForm_Load);
  Self.ResumeLayout(False);
end;
{$ENDREGION}

procedure TWinForm.Dispose(Disposing: Boolean);
begin
  if Disposing then
  begin
    if Components <> nil then
      Components.Dispose();
  end;
  inherited Dispose(Disposing);
end;

constructor TWinForm.Create;
begin
  inherited Create;
  //
  // Required for Windows Form Designer support
  //
  InitializeComponent;
  //
  // TODO: Add any constructor code after InitializeComponent call
  //
  compressor := LZRW1KHCompressor.Create;
end;

procedure TWinForm.btnCompress_Click(sender: System.Object; e: System.EventArgs);
var
  finfo : FileInfo;
  finput :FileStream;
  bwriter : BinaryWriter;
  ms : MemoryStream;
  fs : FileStream;
begin
	finfo := FileInfo.Create(textInput.Text);
	if (finfo.Exists) then
		begin
		 	finput := finfo.OpenRead();
      ms := MemoryStream.Create;
			bwriter := BinaryWriter.Create(ms);
			LZRWCompressFileToStream(finput, bwriter);
			if (bwriter <> nil) then
       begin
  			 fs := FileStream.Create(textOutput.Text,FileMode.Create);
				 bwriter.BaseStream.Seek(0,SeekOrigin(0));
				 (MemoryStream (bwriter.BaseStream)).WriteTo(fs);
				 fs.Close();
				 bwriter.Close();
			 end;
			 finput.Close();
		end;
end;

procedure TWinForm.btnDeCompress_Click(sender: System.Object; e: System.EventArgs);
var
  finfo : FileInfo;
  finput : FileStream;
  breader : BinaryReader;
  ms : MemoryStream;
  fs : FileStream;
begin
 finfo := FileInfo.Create(textInput.Text);
 if (finfo.Exists) then
	 begin
    finput := FileStream.Create(textInput.Text,FileMode.Open,FileAccess.Read);
   	breader := BinaryReader.Create(finput);
		fs := FileStream.Create(textOutput.Text,FileMode.Create);
		try
		  ms := LZRWDeCompressFromStream(breader);
  		if (ms <> nil) then
				begin
 				 ms.WriteTo(fs);
 				 ms.Close();
				end
        else
				  begin
          end;
		 except
     end;
  	 fs.Close();
		 breader.Close();
	 end;
end;

procedure TWinForm.LZRWCompressFileToStream(InStream:Stream; OutStream:BinaryWriter);
 var
	sLength,
	CompIdentifier : UInt32;
  DstSize : word;
 begin
	 try
		//    Compress the lot...
  	//	  Write out compression ID 
		CompIdentifier := UInt32(compressor.LZRWIdentifier);
		OutStream.Write((*UInt32*)(CompIdentifier));
		//	  Write out uncompressed filesize
		sLength := UInt32(InStream.Length);
		OutStream.Write((*UInt32*)(sLength));
    compressor.SourceSize := compressor.ChunkSize;
    InStream.Seek(0,SeekOrigin(0));
		while (compressor.SourceSize = compressor.ChunkSize) do
		 begin
     	//  Read a block of data
		 	compressor.SourceSize := UInt16(InStream.Read(compressor.Source, 0, compressor.ChunkSize));
			//  Compress it
			DstSize := compressor.Compression();
			//  Write out compressed size
			OutStream.Write((*UInt16*)(DstSize));
			//  Write out compressed data
			OutStream.Write(compressor.Destination, 0, DstSize);
		 end;	//while
		except
			OutStream.Close();
			OutStream := nil;
		end;
end; //LZRWSaveToStream

function TWinForm.LZRWDeCompressFromStream(InStream:BinaryReader):MemoryStream;
var
 OutStream : MemoryStream;
 Identifier,
 	OrigSize : UInt32;
	DstSize : word;
 begin
	OutStream := MemoryStream.Create;
	try
  	InStream.BaseStream.Seek(0,SeekOrigin(0));
		//	  Decompress the lot...
		//	  Read compression ID
		Identifier := InStream.ReadUInt32();
		//	  Read in uncompressed filesize
		OrigSize := InStream.ReadUInt32();
		DstSize := compressor.ChunkSize;
		compressor.SourceSize := 0;
		while (DstSize = compressor.ChunkSize) do
		 begin
     	//   Read size of compressed block
		 	compressor.SourceSize :=  InStream.ReadUInt16();
			//	 Read compressed block
			InStream.Read(compressor.Source, 0, compressor.SourceSize);
			//   Decompress block
			DstSize := (compressor.Decompression());
			//	 Write decompressed block out to OutStream
			OutStream.Write(compressor.Destination, 0, DstSize);
		 end;
		OutStream.Seek(0,SeekOrigin(0));
		Result := OutStream;
  except
    OutStream.Free;
		Result :=	nil;
	end;
end;
//LZRWLoadFromStream

procedure TWinForm.TWinForm_Load(sender: System.Object; e: System.EventArgs);
begin

end;

end.
