112fd6cc2SKarsten Heimrich /*
212fd6cc2SKarsten Heimrich * PackBits.cpp
312fd6cc2SKarsten Heimrich * Copyright 1999-2000 Y.Takagi. All Rights Reserved.
412fd6cc2SKarsten Heimrich */
512fd6cc2SKarsten Heimrich
612fd6cc2SKarsten Heimrich //#define DBG_CON_STREAM
712fd6cc2SKarsten Heimrich
812fd6cc2SKarsten Heimrich #ifdef DBG_CON_STREAM
912fd6cc2SKarsten Heimrich #include <fstream>
1012fd6cc2SKarsten Heimrich #endif
1112fd6cc2SKarsten Heimrich
1212fd6cc2SKarsten Heimrich #include <stdio.h>
1312fd6cc2SKarsten Heimrich #include <string.h>
1412fd6cc2SKarsten Heimrich #include "PackBits.h"
1512fd6cc2SKarsten Heimrich
1608d759feSMichael Pfeiffer
1712fd6cc2SKarsten Heimrich using namespace std;
1808d759feSMichael Pfeiffer
1912fd6cc2SKarsten Heimrich
2012fd6cc2SKarsten Heimrich #define MAXINBYTES 127
2112fd6cc2SKarsten Heimrich #define CONTROL1(i) -i
2212fd6cc2SKarsten Heimrich #define CONTROL2(i) i
2312fd6cc2SKarsten Heimrich
2412fd6cc2SKarsten Heimrich enum STATUS {
2512fd6cc2SKarsten Heimrich INITIAL,
2612fd6cc2SKarsten Heimrich UNDECIDED,
2712fd6cc2SKarsten Heimrich UNMATCHED,
2812fd6cc2SKarsten Heimrich MATCHED
2912fd6cc2SKarsten Heimrich };
3012fd6cc2SKarsten Heimrich
31*4410ee12SMichael Pfeiffer #define WRITE_TO_RUN_BUF(byte) \
32*4410ee12SMichael Pfeiffer { \
33*4410ee12SMichael Pfeiffer if (write) \
34*4410ee12SMichael Pfeiffer *runbuf ++ = byte; \
35*4410ee12SMichael Pfeiffer else \
36*4410ee12SMichael Pfeiffer runbuf ++; \
37*4410ee12SMichael Pfeiffer }
38*4410ee12SMichael Pfeiffer
39*4410ee12SMichael Pfeiffer #define WRITE_CONTROL(byte) \
40*4410ee12SMichael Pfeiffer { \
41*4410ee12SMichael Pfeiffer if (write) \
42*4410ee12SMichael Pfeiffer *control = byte; \
43*4410ee12SMichael Pfeiffer }
4412fd6cc2SKarsten Heimrich
4512fd6cc2SKarsten Heimrich template <bool write>
4612fd6cc2SKarsten Heimrich class PackBits {
4712fd6cc2SKarsten Heimrich public:
Run(unsigned char * destination,const unsigned char * source,int n)48*4410ee12SMichael Pfeiffer static int Run(unsigned char* destination, const unsigned char* source, int n)
4912fd6cc2SKarsten Heimrich {
5012fd6cc2SKarsten Heimrich int i;
5112fd6cc2SKarsten Heimrich unsigned char* control;
5212fd6cc2SKarsten Heimrich unsigned char* runbuf;
5312fd6cc2SKarsten Heimrich unsigned char thisbyte;
5412fd6cc2SKarsten Heimrich unsigned char runbyte;
5512fd6cc2SKarsten Heimrich STATUS status;
5612fd6cc2SKarsten Heimrich
5712fd6cc2SKarsten Heimrich i = 0;
5812fd6cc2SKarsten Heimrich status = INITIAL;
59*4410ee12SMichael Pfeiffer control = runbuf = destination;
60*4410ee12SMichael Pfeiffer runbyte = *source++;
6112fd6cc2SKarsten Heimrich
6212fd6cc2SKarsten Heimrich while (--n) {
63*4410ee12SMichael Pfeiffer thisbyte = *source++;
6412fd6cc2SKarsten Heimrich switch (status) {
6512fd6cc2SKarsten Heimrich case INITIAL:
6612fd6cc2SKarsten Heimrich control = runbuf++;
6712fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(runbyte);
6812fd6cc2SKarsten Heimrich if (thisbyte == runbyte) {
6912fd6cc2SKarsten Heimrich status = UNDECIDED;
7012fd6cc2SKarsten Heimrich } else {
7112fd6cc2SKarsten Heimrich runbyte = thisbyte;
7212fd6cc2SKarsten Heimrich status = UNMATCHED;
7312fd6cc2SKarsten Heimrich }
7412fd6cc2SKarsten Heimrich i = 1;
7512fd6cc2SKarsten Heimrich break;
7612fd6cc2SKarsten Heimrich
7712fd6cc2SKarsten Heimrich case UNDECIDED:
7812fd6cc2SKarsten Heimrich if (i == MAXINBYTES) {
7912fd6cc2SKarsten Heimrich WRITE_CONTROL(CONTROL2(i));
8012fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(runbyte);
8112fd6cc2SKarsten Heimrich runbyte = thisbyte;
8212fd6cc2SKarsten Heimrich status = INITIAL;
8312fd6cc2SKarsten Heimrich } else if (thisbyte == runbyte) {
8412fd6cc2SKarsten Heimrich if (i > 1) {
8512fd6cc2SKarsten Heimrich WRITE_CONTROL(CONTROL2(i - 2));
8612fd6cc2SKarsten Heimrich control = runbuf - 1;
8712fd6cc2SKarsten Heimrich }
8812fd6cc2SKarsten Heimrich i = 2;
8912fd6cc2SKarsten Heimrich status = MATCHED;
9012fd6cc2SKarsten Heimrich } else {
9112fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(runbyte);
9212fd6cc2SKarsten Heimrich runbyte = thisbyte;
9312fd6cc2SKarsten Heimrich status = UNMATCHED;
9412fd6cc2SKarsten Heimrich i++;
9512fd6cc2SKarsten Heimrich }
9612fd6cc2SKarsten Heimrich break;
9712fd6cc2SKarsten Heimrich
9812fd6cc2SKarsten Heimrich case UNMATCHED:
9912fd6cc2SKarsten Heimrich if (i == MAXINBYTES) {
10012fd6cc2SKarsten Heimrich WRITE_CONTROL(CONTROL2(i));
10112fd6cc2SKarsten Heimrich status = INITIAL;
10212fd6cc2SKarsten Heimrich } else {
10312fd6cc2SKarsten Heimrich if (thisbyte == runbyte) {
10412fd6cc2SKarsten Heimrich status = UNDECIDED;
10512fd6cc2SKarsten Heimrich }
10612fd6cc2SKarsten Heimrich i++;
10712fd6cc2SKarsten Heimrich }
10812fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(runbyte);
10912fd6cc2SKarsten Heimrich runbyte = thisbyte;
11012fd6cc2SKarsten Heimrich break;
11112fd6cc2SKarsten Heimrich
11212fd6cc2SKarsten Heimrich case MATCHED:
11312fd6cc2SKarsten Heimrich if ((thisbyte != runbyte) || (i == MAXINBYTES)) {
11412fd6cc2SKarsten Heimrich runbuf = control;
11512fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(CONTROL1(i));
11612fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(runbyte);
11712fd6cc2SKarsten Heimrich runbyte = thisbyte;
11812fd6cc2SKarsten Heimrich status = INITIAL;
11912fd6cc2SKarsten Heimrich } else {
12012fd6cc2SKarsten Heimrich i++;
12112fd6cc2SKarsten Heimrich }
12212fd6cc2SKarsten Heimrich break;
12312fd6cc2SKarsten Heimrich }
12412fd6cc2SKarsten Heimrich }
12512fd6cc2SKarsten Heimrich
12612fd6cc2SKarsten Heimrich switch (status) {
12712fd6cc2SKarsten Heimrich case INITIAL:
12812fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(CONTROL2(1));
12912fd6cc2SKarsten Heimrich break;
13012fd6cc2SKarsten Heimrich case UNDECIDED:
13112fd6cc2SKarsten Heimrich case UNMATCHED:
13212fd6cc2SKarsten Heimrich WRITE_CONTROL(CONTROL2(i));
13312fd6cc2SKarsten Heimrich break;
13412fd6cc2SKarsten Heimrich case MATCHED:
13512fd6cc2SKarsten Heimrich runbuf = control;
13612fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(CONTROL1(i));
13712fd6cc2SKarsten Heimrich break;
13812fd6cc2SKarsten Heimrich }
13912fd6cc2SKarsten Heimrich WRITE_TO_RUN_BUF(runbyte);
14012fd6cc2SKarsten Heimrich
141*4410ee12SMichael Pfeiffer return runbuf - destination;
14212fd6cc2SKarsten Heimrich }
14312fd6cc2SKarsten Heimrich };
14412fd6cc2SKarsten Heimrich
14512fd6cc2SKarsten Heimrich
pack_bits_size(const unsigned char * source,int size)146*4410ee12SMichael Pfeiffer int pack_bits_size(const unsigned char* source, int size)
14712fd6cc2SKarsten Heimrich {
148*4410ee12SMichael Pfeiffer PackBits<false> compressedSizeCalculator;
149*4410ee12SMichael Pfeiffer return compressedSizeCalculator.Run(NULL, source, size);
15012fd6cc2SKarsten Heimrich }
15112fd6cc2SKarsten Heimrich
pack_bits(unsigned char * destination,const unsigned char * source,int size)152*4410ee12SMichael Pfeiffer int pack_bits(unsigned char* destination, const unsigned char* source, int size)
15312fd6cc2SKarsten Heimrich {
154*4410ee12SMichael Pfeiffer PackBits<true> compressor;
155*4410ee12SMichael Pfeiffer return compressor.Run(destination, source, size);
15612fd6cc2SKarsten Heimrich }
15712fd6cc2SKarsten Heimrich
15812fd6cc2SKarsten Heimrich #ifdef DBG_CON_STREAM
main(int argc,char ** argv)15912fd6cc2SKarsten Heimrich int main(int argc, char **argv)
16012fd6cc2SKarsten Heimrich {
16112fd6cc2SKarsten Heimrich if (argc < 2) {
16212fd6cc2SKarsten Heimrich return -1;
16312fd6cc2SKarsten Heimrich }
16412fd6cc2SKarsten Heimrich
16512fd6cc2SKarsten Heimrich FILE *input = fopen(*++argv, "rb");
16612fd6cc2SKarsten Heimrich if (input == NULL) {
16712fd6cc2SKarsten Heimrich return -1;
16812fd6cc2SKarsten Heimrich }
16912fd6cc2SKarsten Heimrich
17012fd6cc2SKarsten Heimrich FILE *output = fopen("rle.out", "wb");
17112fd6cc2SKarsten Heimrich if (output == NULL) {
17212fd6cc2SKarsten Heimrich fclose(input);
17312fd6cc2SKarsten Heimrich return -1;
17412fd6cc2SKarsten Heimrich }
17512fd6cc2SKarsten Heimrich
17612fd6cc2SKarsten Heimrich fseek(input, 0, SEEK_END);
17712fd6cc2SKarsten Heimrich long size = ftell(input);
17812fd6cc2SKarsten Heimrich fseek(input, 0, SEEK_SET);
17912fd6cc2SKarsten Heimrich
180*4410ee12SMichael Pfeiffer unsigned char* source = new unsigned char[size];
181*4410ee12SMichael Pfeiffer fread(source, size, 1, input);
18212fd6cc2SKarsten Heimrich
183*4410ee12SMichael Pfeiffer long outSize = pack_bits_size(source, size);
18412fd6cc2SKarsten Heimrich printf("input size: %d\noutput size: %d\n", (int)size, (int)outSize);
18512fd6cc2SKarsten Heimrich
186*4410ee12SMichael Pfeiffer unsigned char* destination = new unsigned char[outSize];
18712fd6cc2SKarsten Heimrich
188*4410ee12SMichael Pfeiffer int cnt = pack_bits(destination, source, size);
18912fd6cc2SKarsten Heimrich
190*4410ee12SMichael Pfeiffer fwrite(destination, cnt, 1, output);
19112fd6cc2SKarsten Heimrich
19212fd6cc2SKarsten Heimrich fclose(input);
19312fd6cc2SKarsten Heimrich fclose(output);
19412fd6cc2SKarsten Heimrich
195*4410ee12SMichael Pfeiffer delete [] source;
196*4410ee12SMichael Pfeiffer delete [] destination;
19712fd6cc2SKarsten Heimrich
19812fd6cc2SKarsten Heimrich }
19912fd6cc2SKarsten Heimrich #endif
200