CK_Compression | +----CK_RLE
Click Here to see the source code for this class
This class provides a simple run-length encoded compression algorithm. It is provided as an example of an implementation of CK_Compression. This compression algorithm is simple, an is not necessarily the best choice for compressing images. It does work reasonably well for images with transparency, since there are often many 'runs' of pixels in the transparent color.
See Compression and CK_Compression for more information.
See the following examples: Example 20, Example 21, Example 22, Example 23
Compresses a memory buffer and returns a new buffer containing the compressed data.
Return Value
- Returns a new buffer holding the compressed data. The size of the new buffer is returned in compressedNumBytes. The returned buffer was allocated with new char[] and therefore should be deleted using delete [].
Parameters
- inputBuffer
- The memory buffer to be compressed.
- inputNumBytes
- The number of bytes in the inputBuffer.
- compressedNumBytes
- The size of the allocated compressed buffer returned.
Decompresses a memory buffer. An output buffer that is large enough to hold the decompressed data must be provided.
Return Value
- Returns 0 if successful. Returns -1 if the outputBuffer is not large enough. The number of decompressed bytes in the outputBuffer is stored in outputNumBytes.
Parameters
- inputBuffer
- The memory buffer to be decompressed.
- inputNumBytes
- The number of bytes in the inputBuffer.
- outputBuffer
- The memory buffer to hold the decompressed data.
- outputNumBytes
- The number of bytes in the outputBuffer is passed in. The number of bytes actually used is stored in this parameter.
ck_rle.h #ifndef _CK_RLE_H #define _CK_RLE_H #ifndef _CK_COMPRESSION_H #include <ck_compression.h> #endif class CK_RLE : public CK_Compression { public: CK_RLE(int id = 1); virtual ~CK_RLE(void); unsigned char *compress(unsigned char *inputBuffer, int inputNumBytes, int &compressedNumBytes); int decompress(unsigned char *inputBuffer, int inputNumBytes, unsigned char *outputBuffer, int &outputNumBytes); }; #endif
ck_rle.cpp #include <ck_rle.h> CK_RLE::CK_RLE(int id) : CK_Compression(id) { } CK_RLE::~CK_RLE(void) { } unsigned char *CK_RLE::compress(unsigned char *buf, int len, int &compressedLen) { int i; // Make the output buffer bigger in case the compressed // data is actually larger! int outBufSize = len+(len*4)/3; unsigned char *out = new unsigned char[outBufSize]; unsigned char *outPtr = out; unsigned char byte1; unsigned char byte2; unsigned char frame_size; unsigned char array[129]; while (len) { byte1 = *buf; buf++; len--; frame_size = 1; if (len) { byte2 = *buf; buf++; len--; frame_size = 2; do { if (byte1 == byte2) { while (len && (byte1 == byte2) && (frame_size < 129)) { byte2 = *buf; buf++; len--; frame_size++; } if (byte1 == byte2) { *outPtr = frame_size+126; outPtr++; *outPtr = byte1; outPtr++; if (len) { byte1=*buf; buf++; len--; frame_size = 1; } else { frame_size = 0; } } else { *outPtr = 125+frame_size; outPtr++; *outPtr = byte1; outPtr++; byte1 = byte2; frame_size = 1; } if (len) { byte2 = *buf; buf++; len--; frame_size = 2; } } else /* Prepare the array of comparisons where will be stored all the identical bytes */ { *array = byte1; array[1] = byte2; while (len && (array[frame_size-2] != array[frame_size-1]) && (frame_size < 128)) { array[frame_size] = *buf; buf++; len--; frame_size++; } /* Do we meet a sequence of all different bytes followed by identical byte? */ if (array[frame_size-2] == array[frame_size-1]) { /* Yes, then don't count the two last bytes */ *outPtr = frame_size-3; outPtr++; for (i=0; i<frame_size-2; i++) { *outPtr = array[i]; outPtr++; } byte1 = array[frame_size-2]; byte2 = byte1; frame_size = 2; } else { *outPtr = frame_size-1; outPtr++; for (i=0; i<frame_size; i++) { *outPtr = array[i]; outPtr++; } if (!len) { frame_size = 0; } else { byte1 = *buf; buf++; len--; if (!len) { frame_size = 1; } else { byte2 = *buf; buf++; len--; frame_size = 2; } } } } } while (len || (frame_size >= 2)); if (frame_size == 1) { *outPtr = 0; outPtr++; *outPtr = byte1; outPtr++; } } } compressedLen = outPtr-out; return out; } int CK_RLE::decompress(unsigned char *buf, int len, unsigned char *out, int &uncompressLen) { unsigned char header; unsigned char *outPtr = out; unsigned char i; int outSize = 0; while (len) { header = *buf; buf++; len--; if (!(header & 128)) { // There are header+1 different bytes. for (i=0; i<=header; i++) { if (outSize >= uncompressLen) return -1; *outPtr = *buf; outPtr++; outSize++; buf++; len--; } } else { const unsigned int n = (header & 127) + 2; for (i=0; i<n; i++) { if (outSize >= uncompressLen) return -1; *outPtr = *buf; outPtr++; outSize++; } buf++; len--; } } uncompressLen = outSize; return 0; }