RLE格式解壓

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 <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>

#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)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章