_DIFFERENTIAL COMPRESSION ALGORITHMS_ by James H. Sylvester [LISTING ONE] /****************************************************************************/ /* PACK.C -- by James Sylvester */ /****************************************************************************/ #include void main(int argc, char *argv[]) { const blockfactor = 1; /* adjust as desired */ const blocksize = blockfactor * 8; char buffer [257] [8]; /* enter blocksize for second index */ int i, j, currentsize; FILE *sf, *tf; /* sourcefile & targetfile respectively */ int bestblock; /* best matching block in buffer */ int bestcount, matchcount; int changeindex, bitvalue; /* Verify and perform error handling for opening both the input file and */ /* the output file as binary files. Note, the input file has the original */ /* data and the output file will contain the encoded/compressed data. */ if (argc != 3) { printf("Correct usage is >pack source_filename target_filename\n"); exit(1); } if ((sf = fopen(argv[1], "rb"))==NULL) /* read only mode for input file */ { printf("Unable to open source file %s\n", argv[1]); exit(2); } if ((tf = fopen(argv[2], "wb"))==NULL) /* write only mode for output file */ { printf("Unable to open target file %s\n", argv[2]); exit(3); } /* Initialize buffer with all zeros in the first block, all ones in the */ /* second block, and so forth so that there will be at least one matching */ /* byte in the first block of input data regardless what it might be. */ for (i = 0; i < 256; i++) for (j = 0; j < blocksize; j++) buffer [i] [j] = i; while (1) /* while true ==> stay in loop until internal exit */ { /* Load the next block of data from the sourcefile into the last slot of */ /* the buffer. Also, keep track of how many bytes were read to signify */ /* proper handling for the unfull block when at the end of file. */ currentsize = blocksize; for (j = 0; j < blocksize; j++) { i = getc(sf); if (i == EOF) { currentsize = j; /* reset correct currentsize */ break; /* exit for loop */ } buffer [256] [j] = i; /* put character into last block */ } if (currentsize == 0) /* input data ended with previous full block */ { printf("%s now contains encoded/compressed data!\n", argv[2]); exit(4); } /* Find the best matching block in buffer for the recently loaded block */ /* of input data. Afterwards, send the bestblock index to the output */ /* file and process the changes between the two blocks. */ bestcount = -1; for (i = 0; i < 256; i++) { matchcount = 0; for (j = 0; j < currentsize; j++) if (buffer [i] [j] == buffer [256] [j]) matchcount++; if (matchcount > bestcount) { bestcount = matchcount; bestblock = i; if (bestcount == currentsize) break; /* exit for loop */ } } putc (bestblock, tf); for (i = 0; i < blockfactor; i++) { changeindex = 0; bitvalue = 1; for (j = i*8; j < i*8+8; j++) { if (j >= currentsize) break; if (buffer [bestblock] [j] != buffer [256] [j]) changeindex += bitvalue; bitvalue *= 2; } putc(changeindex, tf); for (j = i*8; j < i*8+8; j++) { if (changeindex % 2 == 1) putc(buffer [256] [j], tf); changeindex /= 2; } } if (currentsize < blocksize) /* input data ended with unfull block */ { putc(currentsize, tf); printf("%s now contains encoded/compressed data!\n", argv[2]); exit(5); } /* Update the best matching block in buffer with new data. Compression */ /* should improve as further loaded blocks match exact copies in buffer */ for (j = 0; j < blocksize; j++) buffer [bestblock] [j] = buffer [256] [j]; } } /****************************************************************************/ /* UNPACK.C -- by James Sylvester */ /****************************************************************************/ #include void main(int argc, char *argv[]) { const blockfactor = 1; /* adjust as desired */ const blocksize = blockfactor * 8; char buffer [257] [8]; /* enter blocksize for second index */ int i, j; FILE *sf, *tf; /* sourcefile & targetfile respectively */ int bestblock = -1; /* best matching block in buffer */ int changeindex; /* Verify and perform error handling for opening both the input file and the */ /* output file as binary files. Input file contains encoded/compressed data */ /* data and output file should contain an exact copy of the original data. */ if (argc != 3) { printf("Correct usage is >unpack source_filename target_filename\n"); exit(1); } if ((sf = fopen(argv[1], "rb"))==NULL) /* read only mode for input file */ { printf("Unable to open source file %s\n", argv[1]); exit(2); } if ((tf = fopen(argv[2], "wb"))==NULL) /* write only mode for output file */ { printf("Unable to open target file %s\n", argv[2]); exit(3); } /* Initialize buffer with exactly same information as in PACK.C program. */ for (i = 0; i < 256; i++) for (j = 0; j < blocksize; j++) buffer [i] [j] = i; /* Reconstruct original data from encoded data in sourcefile. */ while (1) /* while true ==> stay in loop until internal exit */ { if (bestblock == -1) /* input data yet to be loaded */ { bestblock = getc(sf); if (bestblock == EOF) /* original and encoded files had 0 bytes */ { printf("%s now contains reconstructed original data!\n", argv[2]); exit(4); } changeindex = getc(sf); } else { bestblock = getc(sf); if (bestblock == EOF) /* input data ended with previous full block */ { for (j = 0; j < blocksize; j++) /* output full block */ putc(buffer [256] [j], tf); printf("%s now contains reconstructed original data!\n", argv[2]); exit(5); } changeindex = getc(sf); if (changeindex == EOF) /* input data ended with unfull block */ { for (j = 0; j < bestblock; j++) /* reinterpret bestblock as */ /* last blocksize and output */ /* this last, partial block */ putc(buffer [256] [j], tf); printf("%s now contains reconstructed original data!\n", argv[2]); exit(6); } for (j = 0; j < blocksize; j++) /* output full block */ putc(buffer [256] [j], tf); } for (i = 0; i < blockfactor; i++) { if (i > 0) changeindex = getc(sf); for (j = i*8; j < i*8+8; j++) { if (changeindex % 2 == 1) buffer [bestblock] [j] = getc(sf); /* directly load changes */ /* into buffer bestblock */ changeindex /= 2; buffer [256] [j] = buffer [bestblock] [j]; /* copy block info */ } } } } [LISTING THREE] if (changeindex % 2 == 1) { buffer [256] [j] = getc(sf); } else { buffer [256] [j] = buffer [bestblock] [j]; } changeindex /= 2; } } } }