Chinaunix首页 | 论坛 | 博客
  • 博客访问: 565455
  • 博文数量: 213
  • 博客积分: 6789
  • 博客等级: 准将
  • 技术积分: 1947
  • 用 户 组: 普通用户
  • 注册时间: 2009-09-01 17:11
文章分类

全部博文(213)

文章存档

2012年(9)

2011年(62)

2010年(99)

2009年(43)

分类: LINUX

2010-11-24 17:14:38

 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)
阅读(1454) | 评论(0) | 转发(0) |
0

上一篇:没有了

下一篇:emacs color-theme

给主人留下些什么吧!~~