Tải bản đầy đủ (.doc) (9 trang)

bài phân tích trình LZW 12 mô phỏng thuật toàn kỹ thuật nén dữ liệu.doc.DOC

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (105.24 KB, 9 trang )

Lời nói đầu
Ngày nay, cùng với sự phát triển không ngừng của khoa học và công nghệ thì máy
tính đóng vai trò không thể thiếu trong cuộc sống xã hội loài ngời.
Việc trao đổi thông tin của con ngời trong tất cả các ngành, các lĩnh vực của đời
sống ngày càng trở nên cấp thiết và quan trọng, chính vì thế mà các thiết bị thông
tin mới liên tục ra đời nhằm đáp ứng các yêu cầu này. Tuy nhiên, vì một số phần
mềm đòi hỏi rất nhiều bộ nhớ để hoạt động trao đổi thông tin nên ngời ta đã nghĩ
ra một phơng pháp nhằm giải quyết vấn đề này, đó là phơng pháp nén dữ liệu mà
vẫn bảo toàn thông tin.
Nén dữ liệu là một kỹ thuật quan trọng trong rất nhiều lĩnh vực khác nhau.
Chính nhờ có kỹ thuật nén dữ liệu mà ngày nay chúng ta có những phơng tiện truyền
thông hiện đại phục vụ cho cuộc sống nh truyền hình cáp, điện thoại, th điện tử ... và
rất nhiều khía cạnh khác. Do đó kỹ thuật nén dữ liệu ngày càng đợc quan tâm và phát
triển nhiều hơn. ở Việt Nam, hầu hết các trờng Đại học đều quan tâm đến việc nén dữ
liệu và điều này đợc thể hiện ở việc đa kỹ thuật nén trở thành môn học chính thức
trong giai đoạn chuyên ngành .
Trong phạm vi môn học Mã - mã nén . Tôi đa ra bài phân tích trình LZW 12
nhằm mô phỏng thuật toàn kỹ thuật nén dữ liệu.
Tuy nhiên do trình độ còn hạn chế, thời gian và kinh nghiệm cha nhiều, nên bài
phân tích này không thể tránh khỏi sự sai sót trong quá trình phân tích. Do vậy tôi rất
mong đợc sự quan tâm tham gia góp ý Thầy Cô cũng nh cùng toàn thể các bạn Sinh
Viên để bài phân tích này rõ dàng hơn.
Cuối cùng Em xin chân thành cảm ơn thày Nguyễn Lê Anh đã hớng dẫn và
giảng dạy Em trong thời gian qua.


1
Giải thích stdio.h
Các hàm th viện I/O đợc định nghĩa trong STDIO.H chỉ làm việc ở mức byte, đó
là các hàm putc(), getc(), fread(), fwrite(). Chúng ta cần viết các thủ tục vào/ra ở mức bit.
Cấu trúc BIT_FILE đợc định nghĩa nh sau:


typedef struct bit_file
{
FILE *file;
unsigned char mask;
int rack;
int pacifier_counter;
}
BIT_FILE;
Các thành phần "rack" và "mask" đợc dùng để quản lý theo bit. Rack để chứa byte
dữ liệu hiện thời đợc đọc từ tệp hay đợc ghi vào tệp. Mask chứa 1 bit cờ để đánh dấu
vị trí của bit đang đợc xử lý trong byte.
Các hàm
BIT_FILE *OpenInputFile(char *name)
BIT_FILE *OpenOutputFile(char *name)
void CloseInputBitFile(BIT_FILE *bit_file)
void CloseOutputBitFile(BIT_FILE *bit_file)
đợc dùng để mở tệp hay đóng tệp khi ghi hay đọc. Các hàm này tơng đối đơn giản
nên chúng tôi không gì thích gì thêm.
Hai kiểu thủ tục I/O đợc định nghĩa trong BITIO.H. Hai thủ tục đầu dùng để đọc
và ghi mỗi bit một lần. Hai thủ tục khác dùng để đọc hay ghi nhiều bit một lần.
Đó là các hàm:
void OutputBit( BIT_FILE *bit_file, int bit)
void OutputBits( BIT_FILE *bit_file, unsigned long code, int count)
int InputBit( BIT_FILE *bit_file)
unsigned long InputBits( BIT_FILE *bit_file, int bit_count)
void OutputBit( BIT_FILE *bit_file, int bit)
Trong BITIO.H, bit cao nhất trong byte đợc đọc hay ghi là bít đầu tiên, bit nhỏ
nhất trong byte là bít đợc xử lý cuối. Điều đó có nghĩa là phần tử mask ban đầu sẽ đ-
ợc đặt bằng 0x80. Nếu bit đợc ghi vào tệp là 1 thì thực hiện lệnh
bit_file->rack |= bit_file->mask,

sau đó mask đợc dịch sang trái 1 bit bằng lệnh
bit_file->mask >>=1.
Nếu mask=0 tức là đã tích đợc đủ 8 bit thì lúc đó mới ghi vào tệp bằng lệnh
putc(bit_file->rack, bit_file->file)
Cứ xử lý đợc 2048 byte thì một ký tự (là dấu chấm) lại đợc đa ra màn hình. Sau đó
bắt đầu một rack mới bằng các lệnh
bit_file->rack = 0;
bit_file->mask = 0x80;
void OutputBits( BIT_FILE *bit_file, unsigned long code, int count)
2
Biến count chỉ ra số bit cần ghi (nhiều nhất là 16 bit). Giá trị cần ghi đợc lu ở biến
code.
int InputBit( BIT_FILE *bit_file)
Nếu bit_file->mask==0x80 thì đọc một byte mới từ tệp ra biến bit_file->rack bằng lệnh
bit_file->rack=getc(bit_file->file).
Lấy bit ra bằng lệnh
value=bit_file->rack & bit_file->mask
sau đó dịch mask đi một vị trí bằng lệnh
bit_file->mask >>=1.
Nếu bit_file->mask==0 thì nó đợc đặt lại bằng 0x80.
unsigned long InputBits( BIT_FILE *bit_file, int bit_count)
Đọc bit_count bit từ tệp ra biến return_value. Trong quá trình đọc, các bit đợc lấy ra từ
bit_file->rack. Nếu bit_file->mask==0x80 thì mới đọc byte mới từ tệp ra bằng lệnh
bit_file->rack=getc(bit_file->file)
Một số hàm khác
file_size(char *name) trở về độ dài của tệp.
print_ratios(char *input, char *output) cho biết tỷ lệ nén.
fatal_error(char *fmt,...) thông báo về lỗi mà chúng ta gặp phi. Nó có dùng cấu trúc và
các hàm rất đặc trng cho C, đó là cấu trúc va_list, các hàm va_start và va_end.
prog_name(char *program_name) dùng để lấy riêng tên của chng trình đang chạy (bỏ

phần đờng dẫn và phần mở rộng của tên tệp). Nó đợc dùng kèm khi hớng dẫn cách
chạy chng trình bằng biến Usage.
Chơng Trình LZW12.CPP
#include "bitio.c"
void usage_exit(char *prog_name);
void CompressFile(FILE *input,BIT_FILE *output,int argc,char *argv[]);
void ExpandFile(BIT_FILE *input,FILE *output,int argc,char *argv[]);
char *CompressionName="LZW 12 Bit Encoder ";
char *Usage="in-file out-file \n\n";
void usage_exit(char *prog_name)
{ char *short_name;
char *extension;
short_name = strrchr(prog_name,'\\');
if (short_name == NULL) short_name=strrchr(prog_name,':');
if (short_name!= NULL) short_name++;
else short_name=prog_name;
extension=strrchr(short_name,'.');
if (extension != NULL) *extension='\0';
printf("\nUsage : %s %s \n",short_name,Usage);
exit(0);
}
/*==================================*/
#define BITS 12
#define MAX_CODE ((1<<BITS)-1)
3
#define TABLE_SIZE 5021
#define END_OF_STREAM 256
#define FIRST_CODE 257
#define UNUSED -1
unsigned int find_child_node(int parent_code,int child_character);

unsigned int decode_string(unsigned int offset,unsigned int code);
struct dictionary { int code_value;
int parent_code;
char character;
} dict[TABLE_SIZE];
char decode_stack[TABLE_SIZE];
void CompressFile(FILE *input,BIT_FILE *output,int argc,char *argv[])
{int next_code;
int character;
int string_code;
unsigned int index;
unsigned int i;
next_code=FIRST_CODE;
for (i=0;i<TABLE_SIZE;i++) dict[i].code_value=UNUSED;
if ((string_code=getc(input))==EOF) string_code=END_OF_STREAM;
while ((character=getc(input))!=EOF)
{ index=find_child_node(string_code,character);
if (dict[index].code_value !=-1)
string_code=dict[index].code_value;
else
{ if (next_code <= MAX_CODE)
{ dict[index].code_value=next_code++;
dict[index].parent_code=string_code;
dict[index].character=(char)character;
}
OutputBits(output,(unsigned long)string_code,BITS);
string_code=character;
}
}
OutputBits(output,(unsigned long)string_code,BITS);

OutputBits(output,(unsigned long)END_OF_STREAM,BITS);
while (argc-- >0)
printf("Unknown argument :%s\n",*argv++);
}
/*======================*/
void ExpandFile(BIT_FILE *input,FILE *output,int argc,char *argv[])
{ int next_code;
int new_code;
int old_code;
int character;
unsigned int count;
4
next_code=FIRST_CODE;
old_code=(unsigned int)InputBits(input,BITS);
if (old_code==END_OF_STREAM) return;
character=old_code;
putc(old_code,output);
while((new_code=(unsignedint) InputBits(input,BITS)) != END_OF_STREAM)
{ if (new_code >= next_code)
{ decode_stack[0]=(char)character;
count=decode_string(1,old_code);
}
else count=decode_string(0,new_code);
character=decode_stack[count-1];
while(count>0) putc(decode_stack[--count],output);
if (next_code <= MAX_CODE)
{ dict[next_code].parent_code=old_code;
dict[next_code].character=(char)character;
next_code++;
}

old_code=new_code;
}
while (argc-->0)
printf("Unknown argument:%s",*argv);
}
/*==============================*/
unsigned int find_child_node(int parent_code,int child_character)
{ int index;
int offset;
index=(child_character << (BITS-8)) ^ parent_code;
if (index==0) offset=1;
else offset=TABLE_SIZE-index;
for (;;)
{ if (dict[index].code_value==UNUSED) return(index);
if (dict[index].parent_code==parent_code &&
dict[index].character==(char)child_character)
return(index);
index-=offset;
if(index <0) index+=TABLE_SIZE;
}
}
/*=================================*/
unsigned int decode_string(unsigned int count,unsigned int code)
{
while(code>255)
{ decode_stack[count++]=dict[code].character;
code=dict[code].parent_code;
}
decode_stack[count++]=(char)code;
return(count);

5

×