xref: /haiku/src/libs/print/libprint/PackBits.cpp (revision 26db1794f9199838b3d4c8e6199f72dcf9cfec08)
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