行程码压缩算法

行程码压缩算法原理参考以下链接

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
         
         
        
        
       
       

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值