Title: BitCompression
Question: Why using whole byte to store bynary data when single bit is enough? With this unit you can compress boolean array into byte array in one move.
Answer:
For boolean array we make compressed array of bytes where original boolean values are stored in every bit of byte array, so we save up to 7/8 of original memory space required for storing this array. This could be usefull when you use very large boolean arrays (especially in Pascal) which you cannot define. With this unit you can access particular boolean values with procedure GetBitValue and function SetBitValue. It's almost the same like with ordinary boolean arrays. Just in case, I made decopression routines too.
unit BitCompressionUnit; //1.0
(*
unit by
Storm Software
Branislav Stojkovic
http://branislav.8bit.co.uk
stormbringer@mail.com
*)
interface
type
TCompressedArray=array of byte;
TBooleanArray=array of boolean;
var
CompArray:TCompressedArray;
BoolArray:TBooleanArray;
BitLength:Integer;
function LocateBit(Index:integer; var Cell, Bit:integer):boolean;
procedure SetBitValue(Value:boolean; Index:integer; var CompArray:TCompressedArray);
function GetBitValue(Index:integer; var CompArray:TCompressedArray):boolean;
procedure BitCompress(BoolArray:TBooleanArray; var CompArray:TCompressedArray);
procedure BitDecompress(CompArray:TCompressedArray; var BoolArray:TBooleanArray);
implementation
function LocateBit(Index:integer; var Cell, Bit:integer): boolean;
begin
if ((Index div 8)-1 High(CompArray)) or (Index //index is out of bounds, report error
Result := False
else
begin
//locate array element to write/read and bit index
Cell := Index div 8;
Bit := Index mod 8;
if Bit = 0 then
begin
Dec(Cell);
Bit := 8;
end;
Result := True;
end;
end;
procedure SetBitValue(Value:boolean; Index:integer; var CompArray:TCompressedArray);
var Cell, Bit : integer;
begin
//change element in necessary
if Value then
begin
if LocateBit(Index, Cell, Bit) then
CompArray[Cell] := CompArray[Cell] or (1 shl (Bit-1))
end
else
if LocateBit(Index, Cell, Bit) then
//if target bit is 1 and needs to be set to 0
if Odd(CompArray[Cell] shr (Bit-1)) then
CompArray[Cell] := CompArray[Cell] - (1 shl (Bit-1));
end;
function GetBitValue(Index:integer; var CompArray:TCompressedArray): boolean;
var Cell, Bit : integer;
begin
//get value, shift number to get desired bit to last position
//if it's odd last bit is 1, otherwise it's 0...simple isn't it
if LocateBit(Index, Cell, Bit) then
Result := Odd(CompArray[Cell] shr (Bit-1))
else
Result := False;
end;
procedure BitCompress(BoolArray:TBooleanArray; var CompArray:TCompressedArray);
var i : integer;
begin
//reserve enough bytes to store array of bytes
Finalize(CompArray);
SetLength(CompArray, (High(BoolArray) div 8) + 1);
//remember array length for later use, when decompressing
BitLength := High(BoolArray);
//compress
for i := 0 to High(BoolArray) do
SetBitValue(BoolArray[i], i+1, CompArray);
end;
procedure BitDecompress(CompArray:TCompressedArray; var BoolArray:TBooleanArray);
var i : integer;
begin
//reserve enough bytes to store array of booleans
Finalize(BoolArray);
SetLength(BoolArray, (High(CompArray)+1)*8);
//decompress
for i := 0 to High(BoolArray) do
BoolArray[i]:=GetBitValue(i+1, CompArray);
end;
end.