行程码压缩算法原理参考以下链接
http://www.cnblogs.com/hwl1023/p/5129696.html
以下为具体实现:
1、原始RLE方法
给出的数据序列为:A-A-A-A-A-B-B-C-D
未压缩前:A-A-A-A-A-B-B-C-D
(0x41-0x41-0x41-0x41-0x41-0x42-0x42-0x43-0x44)
压缩后:5-A-2-B-1-C-1-D
(0x05-0x41-0x02-0x42-0x01-0x43-0x01-0x44)
/* Compress inBuf to outBuf
* Input:
* inSize: input buf size
* inBuf: input buf, need compress
* outSize: output buf size, reality outSize <= 2*inSize, but suggest outSize = 2*inSize
* Output:
* outBuf: compressed buf address
* Return:
* 0: Err, input para fault
* 1: Err, outSize < reality compressed buf size
* >= 2: Succ, reality used compressed buf size
*
* List: A-A-A-A-A-B-B-C-D
* Before: A-A-A-A-A-B-B-C-D
* (0x41-0x41-0x41-0x41-0x41-0x42-0x42-0x43-0x44)
* Compressed: 5-A-2-B-1-C-1-D
* (0x05-0x41-0x02-0x42-0x01-0x43-0x01-0x44)
*/
#define RLE_MAX_NUM 0xFF
int RLE_Compress(int inSize, unsigned char *inBuf, int outSize, unsigned char *outBuf)
{
int i=0, j=0;
int rptNum = 0;
if(inSize<=0 || outSize<=0) return 0;
if(!inBuf || !outBuf) return 0;
rptNum = 1;
for(i=0; i
outSize-2) goto done;
outBuf[j++] = rptNum;
outBuf[j++] = inBuf[i];
rptNum = 1;
}else{
if(rptNum == RLE_MAX_NUM){
if(j > outSize-2) goto done;
outBuf[j++] = RLE_MAX_NUM;
outBuf[j++] = inBuf[i];
rptNum = 0;
}
rptNum++;
}
}
if(rptNum > 0){
if(j > outSize-2) goto done;
outBuf[j++] = rptNum;
outBuf[j++] = inBuf[i++];
}
done:
printf("RLE_Compress: inSize=%d, inLen=%d, outSize=%d, cmpSize=%d\n",
inSize, i, outSize, j);
if(i != inSize)
return 1;
else
return j;
}
/* uncompress data
* Input:
* inSize compressed data size
* inBuf compressed data buf
* outSize uncompress data buf size
* Output:
* outBuf uncompress data buf address
* inLen reality use'd compressed data size
* Return:
* <= 0 failure
* > 0 success, reality uncompress data size
*/
int RLE_UnCompress(int inSize, unsigned char *inBuf, int outSize, unsigned char *outBuf, int *inLen)
{
int i=0, j=0;
int len, sign;
if(inSize <= 0 || outSize <= 0) return -1;
if(!inBuf || !outBuf) return -1;
*inLen = 0;
for(i=0; i
0){
if(len+j > outSize){
break;
}
memset(outBuf+j, sign, len);
j += len;
}else{
break;
}
}
*inLen = i;
printf("RLE_UnCompress: inSize=%d inLen=%d, outSize=%d unCmpSize=%d\n", inSize, i, outSize, j);
return j;
}
int RLE_test()
{
int size1, size2;
unsigned char src[]={0x0, 0x13, 0x65, 0x95, 0x65, 0x49, 0x55, 0x65, 0x96,
0x59, 0x5a, 0x65, 0x59, 0x55, 0xa6, 0x65};
// unsigned char src[] = {'a', 'b', 'c', 'd', 'e', 'f'};
unsigned char cmpBuf[1024];
unsigned char uncmpBuf[1024];
size1 = RLE_Compress(sizeof(src), src, 1024, cmpBuf);
printf("size1=%d\n", size1);
int len;
size2 = RLE_UnCompress(size1, cmpBuf, 1024, uncmpBuf, &len);
printf("size2=%d\n", size2);
printf("-----------------src--------------------\n");
for(int i=0; i
2、RLE改进一
下面是RLE改进一的形象举例说明:给出的数据序列为:A-A-A-A-A-B-B-C-D
未压缩前:A-A-A-A-A-B-B-C-D
(0x41-0x41-0x41-0x41-0x41-0x42-0x42-0x43-0x44)
压缩后:5-A-2-B-C-D
(0xC5-0x41-0xC2-0x42-0x43-0x44)
/* Compress inBuf to outBuf
* Input:
* inSize: input buf size
* inBuf: input buf, need compress
* outSize: output buf size, reality outSize <= 2*inSize, but suggest outSize = 2*inSize
* Output:
* outBuf: compressed buf address
* Return:
* 0: Err, input para fault
* 1: Err, outSize < reality compressed buf size
* >= 2: Succ, reality used compressed buf size
*
* List: A-A-A-A-A-B-B-C-D
* Before: A-A-A-A-A-B-B-C-D
* (0x41-0x41-0x41-0x41-0x41-0x42-0x42-0x43-0x44)
* Compressed: 5-A-2-B-C-D
* (0xC5-0x41-0xC2-0x42-0x43-0x44)
*/
#define RLE_ADV1_MAX_NUM 0x3F
#define REL_ADV1_MARK 0xC0
int RLE_ADV1_Compress(int inSize, unsigned char *inBuf, int outSize, unsigned char *outBuf)
{
int i=0, j=0;
int rptNum = 0;
if(inSize<=0 || outSize<=0) return 0;
if(!inBuf || !outBuf) return 0;
rptNum = 1;
for(i=0; i
1){
if(j > outSize - 2) goto done;
outBuf[j++] = rptNum | REL_ADV1_MARK;
outBuf[j++] = inBuf[i];
rptNum = 1;
}else{
if(inBuf[i] >= REL_ADV1_MARK){
if(j > outSize - 2) goto done;
outBuf[j++] = 1 | REL_ADV1_MARK;
outBuf[j++] = inBuf[i];
}else{
if(j > outSize) goto done;
outBuf[j++] = inBuf[i];
}
}
}else{
if(rptNum == RLE_ADV1_MAX_NUM){
if(j > outSize-2) goto done;
outBuf[j++] = RLE_ADV1_MAX_NUM | REL_ADV1_MARK;
outBuf[j++] = inBuf[i];
rptNum = 0;
}
rptNum++;
}
}
if(rptNum > 0){
if(inBuf[i] >= REL_ADV1_MARK){
if(j > outSize - 2) goto done;
outBuf[j++] = 1 | REL_ADV1_MARK;
outBuf[j++] = inBuf[i++];
}else{
if(j > outSize) goto done;
outBuf[j++] = inBuf[i++];
}
}
done:
printf("RLE_ADV1_Compress: inSize=%d, inLen=%d, outSize=%d, cmpSize=%d\n",
inSize, i, outSize, j);
if(i != inSize)
return 1;
else
return j;
}
/* uncompress data
* Input:
* inSize compressed data size
* inBuf compressed data buf
* outSize uncompress data buf size
* Output:
* outBuf uncompress data buf address
* inLen reality use'd compressed data size
* Return:
* <= 0 failure
* > 0 success, reality uncompress data size
*/
int RLE_ADV1_UnCompress(int inSize, unsigned char *inBuf, int outSize, unsigned char *outBuf, int *inLen)
{
int i=0, j=0;
int len;
if(inSize <= 0 || outSize <= 0) return -1;
if(!inBuf || !outBuf) return -1;
*inLen = 0;
for(i=0; i
REL_ADV1_MARK){
// len = inBuf[i] & RLE_ADV1_MAX_NUM;
len = inBuf[i] & ~REL_ADV1_MARK;
if(len+j > outSize){
break;
}
memset(outBuf+j, inBuf[i+1], len);
j += len;
i++;
}else{
if(j >= outSize){
break;
}
outBuf[j++] = inBuf[i];
}
}
if(i == inSize - 1 && inBuf[i] < REL_ADV1_MARK){
if(j < outSize){
outBuf[j++] = inBuf[i++];
}
}
*inLen = i;
printf("RLE_ADV1_UnCompress: inSize=%d inLen=%d, outSize=%d unCmpSize=%d\n", inSize, i, outSize, j);
return j;
}
int RLE_ADV1_test()
{
int size1, size2;
unsigned char src[]={'a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd',
'e', 'e', 'e', 'e', 'e', 'f', 'g', 'h', 0xc0, 0xcf};
// unsigned char src[] = {'a', 'b', 'c', 'd', 'e', 'f'};
unsigned char cmpBuf[1024];
unsigned char uncmpBuf[1024];
size1 = RLE_ADV1_Compress(sizeof(src), src, 1024, cmpBuf);
int len;
size2 = RLE_ADV1_UnCompress(size1, cmpBuf, 1024, uncmpBuf, &len);
printf("-----------------src--------------------\n");
for(int i=0; i
3、RLE改进二
下面是该RLE改进二的形象举例说明:给出的数据序列为:A-A-A-A-A-B-B-C-D
未压缩前:A-A-A-A-A-B-B-C-D
(0x41-0x41-0x41-0x41-0x41-0x42-0x42-0x43-0x44)
压缩后:5-A-4-B-B-C-D
/* Compress inBuf to outBuf
* Input:
* inSize: input buf size
* inBuf: input buf, need compress
* outSize: output buf size, reality outSize <= 2*inSize, but suggest outSize = 2*inSize
* Output:
* outBuf: compressed buf address
* Return:
* 0: Err, input para fault
* 1: Err, outSize < reality compressed buf size
* >= 2: Succ, reality used compressed buf size
*
* List: A-A-A-A-A-B-B-C-D
* Before: A-A-A-A-A-B-B-C-D
*(0x41-0x41-0x41-0x41-0x41-0x42-0x42-0x43-0x44)
* Compressed: 5-A-4-B-B-C-D
* (0x85-0x41-0x84-0x42-0x42-0x43-0x44)
*/
#define RLE_ADV2_MAX_NUM 0x7F
#define REL_ADV2_MARK 0x80
int RLE_ADV2_Compress(int inSize, unsigned char *inBuf, int outSize, unsigned char *outBuf)
{
int i=0, j=0;
int rptNum = 0;
int isRpt = 0;
if(inSize<=0 || outSize<=0) return 0;
if(!inBuf || !outBuf) return 0;
rptNum = 1;
isRpt = 1;
for(i=0; i
2){
if(j > outSize - 2) goto done;
outBuf[j++] = rptNum | REL_ADV2_MARK;
outBuf[j++] = inBuf[i];
rptNum = 0;
}else{
if(rptNum == RLE_ADV2_MAX_NUM){
if(j > outSize - rptNum - 1) goto done;
outBuf[j++] = rptNum;
memcpy(outBuf+j, inBuf+i-rptNum+1, rptNum);
j += rptNum;
rptNum = 0;
}
}
rptNum++;
isRpt = 0;
}else{
if(!isRpt && rptNum > 1){
rptNum--;
if(j > outSize - rptNum - 1) goto done;
outBuf[j++] = rptNum;
memcpy(outBuf+j, inBuf+i-rptNum, rptNum);
j += rptNum;
rptNum = 1;
}
if(rptNum == RLE_ADV2_MAX_NUM){
if(j > outSize-2) goto done;
outBuf[j++] = rptNum | REL_ADV2_MARK;
outBuf[j++] = inBuf[i];
rptNum = 0;
}
rptNum++;
isRpt = 1;
}
}
if(isRpt && rptNum > 2){
if(j > outSize - 2) goto done;
outBuf[j++] = rptNum | REL_ADV2_MARK;
outBuf[j++] = inBuf[i];
}else {
if(j > outSize - rptNum - 1) goto done;
outBuf[j++] = rptNum;
memcpy(outBuf+j, inBuf+i-rptNum+1, rptNum);
j += rptNum;
}
i++;
done:
printf("RLE_ADV2_Compress: inSize=%d, inLen=%d, outSize=%d, cmpSize=%d\n",
inSize, i, outSize, j);
if(i != inSize)
return 1;
else
return j;
}
/* uncompress data
* Input:
* inSize compressed data size
* inBuf compressed data buf
* outSize uncompress data buf size
* Output:
* outBuf uncompress data buf address
* inLen reality use'd compressed data size
* Return:
* <= 0 failure
* > 0 success, reality uncompress data size
*/
int RLE_ADV2_UnCompress(int inSize, unsigned char *inBuf, int outSize, unsigned char *outBuf, int *inLen)
{
int i=0, j=0;
int len;
if(inSize <= 0 || outSize <= 0) return -1;
if(!inBuf || !outBuf) return -1;
*inLen = 0;
while(i
REL_ADV2_MARK){
// len = inBuf[i] & RLE_ADV2_MAX_NUM;
len = inBuf[i] & (~REL_ADV2_MARK);
if(len+j > outSize){
break;
}
memset(outBuf+j, inBuf[i+1], len);
j += len;
i += 2;
}else{
len = inBuf[i];
if(i + 1 + len > inSize){
break;
}
memcpy(outBuf+j, inBuf+i+1, len);
j += len;
i += (len + 1);
}
}
*inLen = i;
printf("RLE_ADV2_UnCompress: inSize=%d inLen=%d, outSize=%d unCmpSize=%d\n", inSize, i, outSize, j);
return j;
}
int RLE_ADV2_test()
{
int size1, size2;
unsigned char src[]={'a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd',
'e', 'e', 'e', 'e', 'e', 'f', 'g', 'h', 0xc0, 0xcf};
// unsigned char src[] = {'a', 'b', 'c', 'd', 'e', 'f'};
unsigned char cmpBuf[1024];
unsigned char uncmpBuf[1024];
size1 = RLE_ADV2_Compress(sizeof(src), src, 1024, cmpBuf);
int len;
size2 = RLE_ADV2_UnCompress(size1, cmpBuf, 1024, uncmpBuf, &len);
printf("-----------------src--------------------\n");
for(int i=0; i
4、RLE改进三
/* Compress inBuf to outBuf
* Input:
* inSize: input buf size
* inBuf: input buf, need compress
* outSize: output buf size, reality outSize <= 2*inSize, but suggest outSize = 2*inSize
* Output:
* outBuf: compressed buf address
* Return:
* 0: Err, input para fault
* 1: Err, outSize < reality compressed buf size
* >= 2: Succ, reality used compressed buf size
*
* List: A-A-A-A-A-B-B-C-D
* Before: A-A-A-A-A-B-B-C-D
*(0x41-0x41-0x41-0x41-0x41-0x42-0x42-0x43-0x44)
* Compressed: 5-A-2-B-2-C-D
* (0x85-0x41-0x82-0x42-0x82-0x43-0x44)
*/
#define RLE_ADV3_MAX_NUM 0x7F
#define REL_ADV3_MARK 0x80
int RLE_ADV3_Compress(int inSize, unsigned char *inBuf, int outSize, unsigned char *outBuf)
{
int i=0, j=0;
int rptNum = 0;
int isRpt = 0;
if(inSize<=0 || outSize<=0) return 0;
if(!inBuf || !outBuf) return 0;
rptNum = 1;
isRpt = 0;
for(i=0; i
outSize - 2) goto done;
if(rptNum == RLE_ADV3_MAX_NUM && j > outSize -3) goto done;
outBuf[j++] = rptNum | REL_ADV3_MARK;
if(rptNum == RLE_ADV3_MAX_NUM) outBuf[j++] = REL_ADV3_MARK;
outBuf[j++] = inBuf[i];
rptNum = 0;
isRpt = 0;
}else{
if(rptNum == RLE_ADV3_MAX_NUM){
if(j > outSize - rptNum - 1) goto done;
outBuf[j++] = rptNum;
memcpy(outBuf+j, inBuf+i-rptNum+1, rptNum);
j += rptNum;
rptNum = 0;
}
}
rptNum++;
}else{
if(!isRpt){
if(rptNum > 1){
rptNum--;
if(j > outSize - rptNum - 1) goto done;
outBuf[j++] = rptNum;
memcpy(outBuf+j, inBuf+i-rptNum, rptNum);
j += rptNum;
}
rptNum = 1;
isRpt = 1;
}
if(rptNum == RLE_ADV3_MAX_NUM){
if(j > outSize-1) goto done;
outBuf[j++] = RLE_ADV3_MAX_NUM | REL_ADV3_MARK;
rptNum = 0;
}
rptNum++;
}
}
if(isRpt){
if(j > outSize - 2) goto done;
if(rptNum == RLE_ADV3_MAX_NUM && j > outSize -3) goto done;
outBuf[j++] = rptNum | REL_ADV3_MARK;
if(rptNum == RLE_ADV3_MAX_NUM) outBuf[j++] = REL_ADV3_MARK;
outBuf[j++] = inBuf[i];
}else {
if(j > outSize - rptNum - 1) goto done;
outBuf[j++] = rptNum;
memcpy(outBuf+j, inBuf+i-rptNum+1, rptNum);
j += rptNum;
}
i++;
done:
printf("RLE_ADV3_Compress: inSize=%d, inLen=%d, outSize=%d, cmpSize=%d\n",
inSize, i, outSize, j);
if(i != inSize)
return 1;
else
return j;
}
/* uncompress data
* Input:
* inSize compressed data size
* inBuf compressed data buf
* outSize uncompress data buf size
* Output:
* outBuf uncompress data buf address
* inLen reality use'd compressed data size
* Return:
* <= 0 failure
* > 0 success, reality uncompress data size
*/
int RLE_ADV3_UnCompress(int inSize, unsigned char *inBuf, int outSize, unsigned char *outBuf, int *inLen)
{
int i=0, j=0;
int len, sum=0;
if(inSize <= 0 || outSize <= 0) return -1;
if(!inBuf || !outBuf) return -1;
*inLen = 0;
while(i
= REL_ADV3_MARK){
// len = inBuf[i] & RLE_ADV3_MAX_NUM;
len = inBuf[i] & (~REL_ADV3_MARK);
sum += len;
if(len == RLE_ADV3_MAX_NUM){
i++;
continue;
}
if(sum+j > outSize){
break;
}
memset(outBuf+j, inBuf[i+1], sum);
j += sum;
i += 2;
sum = 0;
}else{
len = inBuf[i];
if(i + 1 + len > inSize){
break;
}
memcpy(outBuf+j, inBuf+i+1, len);
j += len;
i += (len + 1);
}
}
*inLen = i;
printf("RLE_ADV3_UnCompress: inSize=%d inLen=%d, outSize=%d unCmpSize=%d\n", inSize, i, outSize, j);
return j;
}
int RLE_ADV3_test()
{
int size1, size2;
unsigned char src[]={'a', 'a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'c', 'd',
'e', 'e', 'e', 'e', 'e', 'f', 'g', 'h', 0xc0, 0xcf};
// unsigned char src[] = {'a', 'b', 'c', 'd', 'e', 'f'};
unsigned char cmpBuf[1024];
unsigned char uncmpBuf[1024];
size1 = RLE_ADV3_Compress(sizeof(src), src, 1024, cmpBuf);
cout << "size1=" << size1 << endl;
int len;
size2 = RLE_ADV3_UnCompress(size1, cmpBuf, 1024, uncmpBuf, &len);
cout << "size2=" << size2 << endl;
printf("-----------------src--------------------\n");
for(int i=0; i