home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2000 September
/
Chip_2000-09_cd1.bin
/
sharewar
/
Slunec
/
app
/
16
/
XX3402.ZIP
/
XX3402.HOW
< prev
next >
Wrap
Text File
|
1994-01-28
|
8KB
|
226 lines
HOW XX34 WORKS
The basic premise behind most binary to ASCII encoder/decoders
is to convert an element from a larger range of values, to an
element from a smaller value range.
...Huh? ...Say what?
In other words, you take a binary byte that could have a value
between 0..255, and you convert it to an ASCII character that
can have one of 64 values between '+'..'z' (#43..#122).
...Ok, but a binary byte has a range of 256 different values,
how can you convert this to an ASCII character that has a range
of only 64 different values, and ever hope of getting the
original byte value back again?
The "magic" (logic) relies on those little itty bitty bits that
make up each byte.
Each byte is made up of 8 bits. Each bit can have a value
of either 0 or 1, which gives us a total of 256 different
combinations for each group of 8 bits.
ie: 2 raised to the power of 8 = 256
Now what if we took 24 bits (3 bytes), and split them up into
four groups of 6 bits. Visually it would look something like
this:
Three 8-bit groups: |||||||| |||||||| ||||||||
(256 combinations)
...becomes...
Four 6-bit groups: |||||| |||||| |||||| ||||||
(64 combinations)
Each 6 bit group would then have a range of 64 different
combinations, (2 raised to the power of 6 = 64) and this
range fits within the ASCII character range of '+'..'z'.
ie: (256 x 256 x 256) = (64 x 64 x 64 x 64)
8-Bit Groups 6-Bit Groups
So by processing a binary file in 3 byte chunks, and splitting
("encoding") the 24 bits that these three bytes contain into
four 6 bit groups, you can represent 3 binary bytes using 4
standard alpha-numeric ASCII characters from a total set of
64 ASCII characters.
By reversing this process ("decoding"), you can rebuild the
original 3 bytes, from the 4 ASCII characters that your
encoder produced.
...So if you were encoding three 8-bit groups that were:
Byte value : 255 240 15
Bit pattern: 11111111 11110000 00001111
...You would end up with four 6-bit groups that are:
Byte value : 63 63 0 15
Bit pattern: 111111 111111 000000 001111
...Now by defining a Pascal 64 ASCII character array like so:
type
Array64 = array[0..63] of char;
...And using this "Array64" type to define a "typed constant" :
const
EncodedSet : Array64 =
'+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
You can then translate those initial three 8-bit numbers,
(255, 240, 15) into four 6-bit numbers (63, 63, 0, 15).
NOTE: Turbo Pascal allows you to move bits around by using the
"SHL" and "SHR" operators.
The "AND" operator is necessary to "mask-out" specific
"high" bits, and stop bytes from from "over-flowing" the
valid byte number range.
The "OR" operator combines the "masked" bit-patterns back
into a single byte value.
BinByte1 := 255;
BinByte2 := 240;
BinByte3 := 15;
TempByte1 := BinByte1 shr 2;
TempByte2 := ((BinByte1 AND 3) SHL 4) OR (BinByte2 SHR 4);
TempByte3 := ((BinByte2 AND 15) SHL 2) OR (BinByte3 SHR 6);
TempByte4 := BinByte3 AND 63;
...And finally into four standard ASCII characters:
EncodedChar1 := EncodedSet[TempByte1]; (* ASCII char = 'z' *)
EncodedChar2 := EncodedSet[TempByte2]; (* ASCII char = 'z' *)
EncodedChar3 := EncodedSet[TempByte3]; (* ASCII char = '+' *)
EncodedChar4 := EncodedSet[TempByte4]; (* ASCII char = 'C' *)
...So after you've encoded the 3 bytes, you end up with the four
ASCII chars, 'zz+C'.
By reversing this process ("decoding"), you can rebuild the
original 3 bytes, from the 4 ASCII characters that your encoder
produced. To make this a simple/quick process, we could build
the following "look-up" (translation) table:
type
Byte80 = array[43..122] of byte;
const
BinSet : Byte80 = ( 0, 0, 1, 0, 0, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 0, 0, 0, 0, 0,
0, 0, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 0, 0,
0, 0, 0, 0, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
54, 55, 56, 57, 58, 59, 60, 61, 62, 63);
...So to get my original four 6-bit numbers back:
TempByte1 := BinSet[ord('z')]; (* TempByte = 63 *)
TempByte2 := BinSet[ord('z')]; (* TempByte = 63 *)
TempByte3 := BinSet[ord('+')]; (* TempByte = 0 *)
TempByte4 := BinSet[ord('C')]; (* TempByte = 15 *)
...and then translate these four 6-bit numbers (63, 63, 0, 15)
back into three 8-bit numbers (255, 240, 15):
BinByte1 := (TempByte1 SHL 2) OR (TempByte2 SHR 4);
BinByte2 := ((TempByte2 AND 15) SHL 4) OR (TempByte3 SHR 2);
BinByte3 := ((TempByte3 and 3) SHL 6) OR (TempByte4 AND 63);
TURNING THEORY INTO REALITY
So now that we all know how the process works, we need to put
the theory into a finished program.
First of all we need to create two data buffers. One to hold
the original binary file data, and another to hold the encoded
data. Buffers are needed because, your program will be as fast
as a salted slug if you don't buffer the data being read/written
to/from disk. (ie: Disk I/O is MUCH slower than moving data
around in RAM.)
To simplify the encoding/decoding process a little, we'll set
the size of these two buffers by determining the size of the
largest binary/encoded text block we want to encode/decode.
In this case the largest encoded text block is 100 columns by
200 rows of text:
Encoded text block size : (200 rows) * (100 columns)
Plus the CrLf's for each row: (200 rows) * 2 bytes
===========================================================
Total = 20,400 bytes
...Next we need to calculate the binary block buffer:
Binary block size: (200 rows) * (100 columns) * 3/4
=========================================================
Total = 15,000 bytes
Once the buffers sizes have been determined, the complete
encoding process would be something like this:
1- Open binary file.
2- Open the encoded text file.
3- Load the binary file into the binary buffer.
4- Encode from binary buffer to encoded text buffer.
5- Once a complete binary-block has been encoded, write
the encoded text buffer out to the encoded text file.
6- Repeat steps 3-5 until the entire binary file has been
completely encoded.
7- Close files.
...The Decoding process is pretty much the same in reverse.
1- Open encoded text file.
2- Open binary file.
3- Load encoded text buffer from encoded text file.
4- Decode from the encoded text buffer to binary buffer.
5- Once a complete binary block has been decoded, write
the binary buffer out to the new binary file.
6- Repeat steps 3-5 until the entire binary file has been
completely decoded.
7- Close files.
This is a great simplification of the complete process,
though it should give you the basic idea of how the
binary/text encoding/decoding process works. For a more
detailed look, take a look at the included XX3402.PAS
source-code included with this archive.
- Guy