1、行程编码
嵌入式设备采集的数据,变化比较平缓,长时间趋于稳定的状态,其采样结果会有大量连续且相同的数值,对应这些数据,常规的压缩算法在硬件资源有限的嵌入式设备无法运行,代码空间和RAM要求不能满足的情况下,简单有效的行程编码不失为一种最佳选择。
行程编码(Run Length Encoding,RLE), 又称游程编码,主要思路是将一个相同值的连续串用一个代表值和串长来代替。例如字符串“AAABBBBCCCCCJJJJJJ”,可以用“3A4B5C6J”来记录,原本长度18字节的字符串使用8个字节即可无损表达。
为便于直观显示,举例的编码是进行了特殊描述,“3A4B5C6J”实际应该是 3‘A’ 4‘B’ 5‘C’ 6‘J’,字符个数的数字转为字符显示,例如3变成了‘3’显示更易理解。
以下举例也是这个规则,正确方式是应该是以%X查看,如果不明白3和‘3’的区别,请先补习C基础。
2、局限性与改进型
行程编码的原理简单,但算法需结合实际,统计数据出现概率与次数,有针对性的改进编码,提高压缩比。
- 按前面范例规则,原始数据全部都不连续出现,如源字符串“ABCDE”编码后变成“1A1B1C1D1E”,其长度反而扩大一倍,因此对于随机出现没有连续字符的数据,基本规则不适合。
- 可以改进为编码时查询连续出现的才进行编码,只出现一次的直接使用原始值,不进行处理。如"111233334"编码为“31 2 43 4”,字符2和4只出现一次,编码时忽略。但缺点是解码无法分辨其中的2是数值出现次数,还是数值本身。
- 因此对编码与未编码的分段,使用标记区分段。例如定义编码段以E开头,则"111233334"编码为“E31 2 E43 4”,解析时只对出现E的字段才进行解析,单个字段直接原样替换。
- 增加段标记后,每个连续段编码后都是3个字节,如果相同字符值出现2次,如“11335577”则编码后为“E21 E23 E25 E27”,其长度超过原始长度,因此可以改为,只有连续出现的次数大于3的才进行编码。例如"112223333"编码为“11 222 E43”。
- 因为表示字符连续次数的数字分配了一个字节,某个字符如连续出现255次以上,则拆分为两部分。如“AAA…AAA”连续出现300次,则编码以%X显示为 45 FF 41 45 2D 41 ,其中’E’=0x45,‘A’=0x41。
45 FF 41 //行程编码 255 个’A’
45 2D 41 //行程编码 45 个’A’
- 前面描述编码段的头以’E’作为标记,字符连续出现次数大于3的才进行编码处理的,因此 ‘E’ 后面的数字肯定大于3。如果源数据中存在‘E’,则以 ‘E’0转义,这样才能解析分辨,是真实的’E’,还是编码标记。
如 “EEEEE”编码后以16进制显示为 45 00 45 00 45 00 45 00 45 00 ,结果是长度增加一倍,因此定义合理的标记很关键。
选择字数据串中出现概率最小的为标记。如纯ASCII字符串(0-0x7F),选择0x80则避开该问题。
- 算法规则没有最好的,只有最合适的,如果认可前面的规则,可继续阅读下面的源码,包括编码和解码。
3、源码
#include "stdio.h"
#include "string.h"
//配置为数据源中出现概率最小的数
#define FLAG_ENCODE_HEAD 0x80
void log(char *head,unsigned char *data,unsigned int len)
{
unsigned int i;
printf("%s:",head);
for(i=0;i<len;i++)
{
printf("%02X ",data[i]);
}
printf("\r\n");
}
//行程编码
//输入待编码的数据及长度,提供输出编码数据的缓冲区
//返回编码后的长度
int compress_encode(unsigned char *dect, unsigned char *src, unsigned int len)
{
unsigned char last = 0, count
行程编码:优化连续重复数据的高效压缩策略

最低0.47元/天 解锁文章
3879

被折叠的 条评论
为什么被折叠?



