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