/* * PackBits.cpp * Copyright 1999-2000 Y.Takagi. All Rights Reserved. */ //#define DBG_CON_STREAM #ifdef DBG_CON_STREAM #include #endif #include #include #include "PackBits.h" using namespace std; #define MAXINBYTES 127 #define CONTROL1(i) -i #define CONTROL2(i) i enum STATUS { INITIAL, UNDECIDED, UNMATCHED, MATCHED }; #define WRITE_TO_RUN_BUF(byte) \ { \ if (write) \ *runbuf ++ = byte; \ else \ runbuf ++; \ } #define WRITE_CONTROL(byte) \ { \ if (write) \ *control = byte; \ } template class PackBits { public: static int Run(unsigned char* destination, const unsigned char* source, int n) { int i; unsigned char* control; unsigned char* runbuf; unsigned char thisbyte; unsigned char runbyte; STATUS status; i = 0; status = INITIAL; control = runbuf = destination; runbyte = *source++; while (--n) { thisbyte = *source++; switch (status) { case INITIAL: control = runbuf++; WRITE_TO_RUN_BUF(runbyte); if (thisbyte == runbyte) { status = UNDECIDED; } else { runbyte = thisbyte; status = UNMATCHED; } i = 1; break; case UNDECIDED: if (i == MAXINBYTES) { WRITE_CONTROL(CONTROL2(i)); WRITE_TO_RUN_BUF(runbyte); runbyte = thisbyte; status = INITIAL; } else if (thisbyte == runbyte) { if (i > 1) { WRITE_CONTROL(CONTROL2(i - 2)); control = runbuf - 1; } i = 2; status = MATCHED; } else { WRITE_TO_RUN_BUF(runbyte); runbyte = thisbyte; status = UNMATCHED; i++; } break; case UNMATCHED: if (i == MAXINBYTES) { WRITE_CONTROL(CONTROL2(i)); status = INITIAL; } else { if (thisbyte == runbyte) { status = UNDECIDED; } i++; } WRITE_TO_RUN_BUF(runbyte); runbyte = thisbyte; break; case MATCHED: if ((thisbyte != runbyte) || (i == MAXINBYTES)) { runbuf = control; WRITE_TO_RUN_BUF(CONTROL1(i)); WRITE_TO_RUN_BUF(runbyte); runbyte = thisbyte; status = INITIAL; } else { i++; } break; } } switch (status) { case INITIAL: WRITE_TO_RUN_BUF(CONTROL2(1)); break; case UNDECIDED: case UNMATCHED: WRITE_CONTROL(CONTROL2(i)); break; case MATCHED: runbuf = control; WRITE_TO_RUN_BUF(CONTROL1(i)); break; } WRITE_TO_RUN_BUF(runbyte); return runbuf - destination; } }; int pack_bits_size(const unsigned char* source, int size) { PackBits compressedSizeCalculator; return compressedSizeCalculator.Run(NULL, source, size); } int pack_bits(unsigned char* destination, const unsigned char* source, int size) { PackBits compressor; return compressor.Run(destination, source, size); } #ifdef DBG_CON_STREAM int main(int argc, char **argv) { if (argc < 2) { return -1; } FILE *input = fopen(*++argv, "rb"); if (input == NULL) { return -1; } FILE *output = fopen("rle.out", "wb"); if (output == NULL) { fclose(input); return -1; } fseek(input, 0, SEEK_END); long size = ftell(input); fseek(input, 0, SEEK_SET); unsigned char* source = new unsigned char[size]; fread(source, size, 1, input); long outSize = pack_bits_size(source, size); printf("input size: %d\noutput size: %d\n", (int)size, (int)outSize); unsigned char* destination = new unsigned char[outSize]; int cnt = pack_bits(destination, source, size); fwrite(destination, cnt, 1, output); fclose(input); fclose(output); delete [] source; delete [] destination; } #endif