RLE算法
这种压缩编码是一种变长的编码,RLE根据文本不同的具体情况会有不同的压缩编码变体与之相适应,以产生更大的压缩比率。
变体1:重复次数+字符
文本字符串:A A A B B B C C C C D D D D,编码后得到:3 A 3 B 4 C 4 D。
变体2:特殊字符+重复次数+字符
文本字符串:A A A A A B C C C C B C C C,编码后得到:B B 5 A B B 4 C B B 3 C。编码串的最开始说明特殊字符B,以后B后面跟着的数字就表示出重复的次数。
变体3:把文本每个字节分组成块,每个字符最多重复 127 次。每个块以一个特殊字节开头。那个特殊字节的第 7 位如果被置位,那么剩下的7位数值就是后面的字符的重复次数。如果第 7 位没有被置位,那么剩下 7 位就是后面没有被压缩的字符的数量。例如:文本字符串:A A A A A B C D E F F F。编码后得到:85 A 4 B C D E 83 F(85H= 10000101B、4H= 00000100B、83H= 10000011B)
以上3种不RLE变体是最常用的几种,其他还有很多很多变体算法,这些算法在Winzip Winrar这些软件中也是经常用到的。
变体1相关解压代码:
#cat unrle.c
#include
#include
#include
#include
#include
#include
#define CTL_BIT (1 << 8)
#define DATA_NUMBER (0x7F)
int fd_input;
int fd_output;
int size = 0;
void ctl_bit_set(char *input, char *output)
{
static int times = 5;
int i = 0;
char number = 0;
char data;
number = input[0];
number = (char)(DATA_NUMBER & number);
data = input[1];
for(i = 0; i < number; ++i)
write(fd_output, &data, 1);
if (times != 0 ){
printf("data = %x\n", data);
printf("number = %x\n", number);
times--;
}
}
void only_trans_data(char *input, char *output, int *counts)
{
static int times = 5;
int i = 0;
char number = 0;
char buffer[127] = {0};
number = *input++;
for( i = 0; i < number; ++i)
buffer[i] = *input++;
write(fd_output, buffer, number);
*counts = (number + 1);
if (times != 0 ){
printf("only number = %d\n", number);
printf("only counts = %d\n", *counts);
times--;
}
}
void unrle(char *input, char *output)
{
int i = 0;
int counts = 0;
size -= 4;
input = input+4;
printf("size = %d\n", size);
for ( i = 0 ; i < size ;){
if( *input & CTL_BIT ){
ctl_bit_set(input, output);
input += 2;
i += 2;
}
else{
only_trans_data(input, output, &counts);
input += counts;
i += counts;
}
}
}
int main(int argc, char *argv[])
{
char input[1024*400];
char output[1024*400];
int fd_read_input;
struct stat st;
fd_input = open(argv[1], O_RDONLY );
if (fd_input == -1) {
printf("Cannot open %s!\n",argv[1]);
exit(-1);
}
fd_output = open(argv[2], O_RDWR | O_CREAT );
if (fd_output == -1) {
printf("Cannot open %s!\n",argv[2]);
exit(-1);
}
if(!stat(argv[1], &st))
printf("%s size is %ld\n", argv[1], st.st_size);
fd_read_input = read(fd_input, input, st.st_size);
size = fd_read_input;
printf("size = %d\n", size);
unrle(input, output);
close(fd_input);
close(fd_output);
return 0;
}
#gcc unrle.c -Wall -o unrle
#unrle input(压缩过的文件path) output(解压出来的文件path)
阅读(1507) | 评论(0) | 转发(0) |