当前位置:文档之家› LZSS压缩算法实验报告

LZSS压缩算法实验报告

LZSS压缩算法实验报告
LZSS压缩算法实验报告

实验名称:LZSS压缩算法实验报告

一、实验内容

使用Visual 6..0 C++编程实现LZ77压缩算法。

二、实验目的

用LZSS实现文件的压缩。

三、实验原理

LZSS压缩算法是词典编码无损压缩技术的一种。LZSS压缩算法的字典模型使用了自适应的方式,也就是说,将已经编码过的信息作为字典,

四、实验环境

1、软件环境:Visual C++ 6.0

2、编程语言:C++

五、实验代码

#include

#include

#include

#include

/* size of ring buffer */

#define N 4096

/* index for root of binary search trees */

#define NIL N

/* upper limit for g_match_len. Changed from 18 to 16 for binary

compatability with Microsoft COMPRESS.EXE and EXPAND.EXE

#define F 18 */

#define F 16

/* encode string into position and length

if match_length is greater than this: */

#define THRESHOLD 2

/* these assume little-endian CPU like Intel x86

-- need byte-swap function for big endian CPU */

#define READ_LE32(X) *(uint32_t *)(X)

#define WRITE_LE32(X,Y) *(uint32_t *)(X) = (Y)

/* this assumes sizeof(long)==4 */

typedef unsigned long uint32_t;

/* text (input) size counter, code (output) size counter,

and counter for reporting progress every 1K bytes */

static unsigned long g_text_size, g_code_size, g_print_count;

/* ring buffer of size N, with extra F-1 bytes

to facilitate string comparison */

static unsigned char g_ring_buffer[N + F - 1];

/* position and length of longest match; set by insert_node() */

static unsigned g_match_pos, g_match_len;

/* left & right children & parent -- these constitute binary search tree */

static unsigned g_left_child[N + 1], g_right_child[N + 257], g_parent[N + 1];

/* input & output files */

static FILE *g_infile, *g_outfile;

/***************************************************************************** initialize trees

*****************************************************************************/ static void init_tree(void)

{

unsigned i;

/* For i = 0 to N - 1, g_right_child[i] and g_left_child[i] will be the right and left children of node i. These nodes need not be initialized.

Also, g_parent[i] is the parent of node i. These are initialized to

NIL (= N), which stands for 'not used.'

For i = 0 to 255, g_right_child[N + i + 1] is the root of the tree

for strings that begin with character i. These are initialized

to NIL. Note there are 256 trees. */

for(i = N + 1; i <= N + 256; i++)

g_right_child[i] = NIL;

for(i = 0; i < N; i++)

g_parent[i] = NIL;

}

/***************************************************************************** Inserts string of length F, g_ring_buffer[r..r+F-1], into one of the

trees (g_ring_buffer[r]'th tree) and returns the longest-match position

and length via the global variables g_match_pos and g_match_len.

If g_match_len = F, then removes the old node in favor of the new

one, because the old one will be deleted sooner.

Note r plays double role, as tree node and position in buffer.

*****************************************************************************/ static void insert_node(int r)

{

unsigned char *key;

unsigned i, p;

int cmp;

cmp = 1;

key = &g_ring_buffer[r];

p = N + 1 + key[0];

g_right_child[r] = g_left_child[r] = NIL;

g_match_len = 0;

while(1)

{

if(cmp >= 0)

{

if(g_right_child[p] != NIL)

p = g_right_child[p];

else

{

g_right_child[p] = r;

g_parent[r] = p;

return;

}

}

else

{

if(g_left_child[p] != NIL)

p = g_left_child[p];

else

{

g_left_child[p] = r;

g_parent[r] = p;

return;

}

}

for(i = 1; i < F; i++)

{

cmp = key[i] - g_ring_buffer[p + i];

if(cmp != 0)

break;

}

if(i > g_match_len)

{

g_match_pos = p;

g_match_len = i;

if(g_match_len >= F)

break;

}

}

g_parent[r] = g_parent[p];

g_left_child[r] = g_left_child[p];

g_right_child[r] = g_right_child[p];

g_parent[g_left_child[p]] = r;

g_parent[g_right_child[p]] = r;

if(g_right_child[g_parent[p]] == p)

g_right_child[g_parent[p]] = r;

else

g_left_child[g_parent[p]] = r;

g_parent[p] = NIL; /* remove p */

}

/***************************************************************************** deletes node p from tree

*****************************************************************************/ static void delete_node(unsigned p)

{

unsigned q;

if(g_parent[p] == NIL)

return; /* not in tree */

if(g_right_child[p] == NIL)

q = g_left_child[p];

else if(g_left_child[p] == NIL)

q = g_right_child[p];

else

{

q = g_left_child[p];

if(g_right_child[q] != NIL)

{

do q = g_right_child[q];

while(g_right_child[q] != NIL);

g_right_child[g_parent[q]] = g_left_child[q];

g_parent[g_left_child[q]] = g_parent[q];

g_left_child[q] = g_left_child[p];

g_parent[g_left_child[p]] = q;

}

g_right_child[q] = g_right_child[p];

g_parent[g_right_child[p]] = q;

}

g_parent[q] = g_parent[p];

if(g_right_child[g_parent[p]] == p)

g_right_child[g_parent[p]] = q;

else

g_left_child[g_parent[p]] = q;

g_parent[p] = NIL;

}

/***************************************************************************** *****************************************************************************/ static void compress(void)

{

unsigned i, len, r, s, last_match_length, code_buf_ptr;

unsigned char code_buf[17], mask;

int c;

init_tree(); /* initialize trees */

/* code_buf[1..16] saves eight units of code, and code_buf[0] works as

eight flags, "1" representing that the unit is an unencoded letter (1 byte),

"0" a position-and-length pair (2 bytes). Thus, eight units require at most

16 bytes of code. */

code_buf[0] = 0;

code_buf_ptr = mask = 1;

s = 0;

r = N - F;

/* Clear the buffer with any character that will appear often. */

memset(g_ring_buffer + s, ' ', r - s);

/* Read F bytes into the last F bytes of the buffer */

for(len = 0; len < F; len++)

{

c = getc(g_infile);

if(c == EOF)

break;

g_ring_buffer[r + len] = c;

}

g_text_size = len;

if(g_text_size == 0) /* text of size zero */

return;

/* Insert the F strings, each of which begins with one or more 'space'

characters. Note the order in which these strings are inserted.

This way, degenerate trees will be less likely to occur. */

for(i = 1; i <= F; i++)

insert_node(r - i);

/* Finally, insert the whole string just read. The global variables

g_match_len and g_match_pos are set. */

insert_node(r);

do

{

/* g_match_len may be spuriously long near the end of text. */

if(g_match_len > len)

g_match_len = len;

/* Not long enough match. Send one byte. */

if(g_match_len <= THRESHOLD)

{

g_match_len = 1;

code_buf[0] |= mask; /* 'send one byte' flag */

code_buf[code_buf_ptr] = g_ring_buffer[r]; /* Send uncoded. */

code_buf_ptr++;

/* Send position and length pair. Note g_match_len > THRESHOLD. */ }

else

{

code_buf[code_buf_ptr] = (unsigned char)g_match_pos;

code_buf_ptr++;

code_buf[code_buf_ptr] = (unsigned char)

(((g_match_pos >> 4) & 0xF0) |

(g_match_len - (THRESHOLD + 1)));

code_buf_ptr++;

}

/* Shift mask left one bit. */

mask <<= 1;

if(mask == 0)

{

/* Send at most 8 units of code together */

for(i = 0; i < code_buf_ptr; i++)

putc(code_buf[i], g_outfile);

g_code_size += code_buf_ptr;

code_buf[0] = 0;

code_buf_ptr = mask = 1;

}

last_match_length = g_match_len;

for(i = 0; i < last_match_length; i++)

{

c = getc(g_infile);

break;

/* Delete old strings and read new bytes */

delete_node(s);

g_ring_buffer[s] = c;

/* If the position is near the end of buffer, extend the buffer

to make string comparison easier. */

if(s < F - 1)

g_ring_buffer[s + N] = c;

/* Since this is a ring buffer, increment the position modulo N. */

s = (s + 1) & (N - 1);

r = (r + 1) & (N - 1);

/* Register the string in g_ring_buffer[r..r+F-1] */

insert_node(r);

}

/* Reports progress each time the g_text_size exceeds multiples of 1024. */

g_text_size += i;

if(g_text_size > g_print_count)

{

printf("%12ld\r", g_text_size);

g_print_count += 1024;

}

while(i++ < last_match_length)/* After the end of text, */

{

delete_node(s); /* no need to read, but */

s = (s + 1) & (N - 1);

r = (r + 1) & (N - 1);

len--;

if(len)

insert_node(r);/* buffer may not be empty. */

}

} while(len > 0); /* until length of string to be processed is zero */

/* Send remaining code. */

if(code_buf_ptr > 1)

{

for(i = 0; i < code_buf_ptr; i++)

putc(code_buf[i], g_outfile);

g_code_size += code_buf_ptr;

}

/* Encoding is done. */

printf("In : %ld bytes\n", g_text_size);

printf("Out: %ld bytes\n", g_code_size);

/* xxx - floating-point math: */

printf("Out/In: %.3f\n", (double)g_code_size / g_text_size);

}

/***************************************************************************** Just the reverse of compress()

*****************************************************************************/ static void decompress(void)

{

unsigned r, flags;

int c, i, j, k;

memset(g_ring_buffer, ' ', N - F);

r = N - F;

for(flags = 0; ; flags >>= 1)

{

/* Get a byte. For each bit of this byte:

1=copy one byte literally, from input to output

0=get two more bytes describing length and position of previously-seen

data, and copy that data from the ring buffer to output */

if((flags & 0x100) == 0)

{

c = getc(g_infile);

if(c == EOF)

break;

/* uses higher byte cleverly to count eight */

flags = c | 0xFF00;

}

/* 1=copy one byte literally, from input to output */

if(flags & 1)

{

c = getc(g_infile);

if(c == EOF)

break;

putc(c, g_outfile);

g_ring_buffer[r] = c;

r = (r + 1) & (N - 1);

}

/* 0=get two more bytes describing length and position of previously-

seen data, and copy that data from the ring buffer to output */

else

{

i = getc(g_infile);

if(i == EOF)

break;

j = getc(g_infile);

if(j == EOF)

break;

i |= ((j & 0xF0) << 4);

j = (j & 0x0F) + THRESHOLD;

for(k = 0; k <= j; k++)

{

c = g_ring_buffer[(i + k) & (N - 1)];

putc(c, g_outfile);

g_ring_buffer[r] = c;

r = (r + 1) & (N - 1);

}

}

}

}

/***************************************************************************** *****************************************************************************/ int main(int arg_c, char *arg_v[])

{

char ms_hdr[14] = "SZDD堭'3A";

unsigned long size;

/* check args */

if(arg_c != 4)

USAGE: {

printf("'lzss c file1 file2' compresses file1 into file2\n"

"'lzss u file2 file1' uncompresses file2 into file1\n");

return 1;

}

if(strpbrk(arg_v[1], "CcUu") == NULL)

goto USAGE;

/* open input file */

g_infile = fopen(arg_v[2], "rb");

if(g_infile == NULL)

{

printf("Can't open input file '%s'\n", arg_v[2]);

return 2;

}

/* get size of (uncompressed) input file */

fseek(g_infile, 0, SEEK_END);

size = ftell(g_infile);

fseek(g_infile, 0, SEEK_SET);

/* open output file */

g_outfile = fopen(arg_v[3], "wb");

if(g_outfile == NULL)

{

printf("Can't open output file '%s'\n", arg_v[3]);

fclose(g_infile);

return 2;

}

/* compress or decompress */

if(toupper(*arg_v[1]) == 'C')

{

/* write Microsoft COMPRESS/EXPAND header */

WRITE_LE32(ms_hdr + 10, size);

if(fwrite(ms_hdr, 1, 14, g_outfile) != 14)

{

printf("Error writing output file '%s'\n", arg_v[3]);

fclose(g_infile);

fclose(g_outfile);

remove(arg_v[3]);

}

compress();

}

else

{

/* read and validate Microsoft COMPRESS/EXPAND header */ if(fread(ms_hdr, 1, 14, g_infile) != 14)

{

printf("Error reading input file '%s'\n", arg_v[2]);

fclose(g_infile);

fclose(g_outfile);

remove(arg_v[3]);

}

if(strncmp(ms_hdr, "SZDD堭'3A", 9))

{

printf("Input file '%s' is not COMPRESSed\n",

arg_v[2]);

fclose(g_infile);

fclose(g_outfile);

remove(arg_v[3]);

}

size = READ_LE32(ms_hdr + 10);

decompress();

}

fclose(g_infile);

fclose(g_outfile);

return 0;

}

六、实验结果

矢量数据主要压缩方法及比较

矢量数据主要压缩方法及比较 张旭 测绘工程 211305020021 摘要:矢量数据主要是指城市大比例尺地形图。此系统中图层主要分为底图层、道路层、单位层,合理的分层便于进行叠加分析、图形的 阐述矢量数据压缩的概念,详细的对常见的矢量空间数据压缩方法了介绍与评价,并对一些改进方法做了介绍,希望通过本文的总结,大家能够更好地了解矢量数据及其压缩方法。 关键词:矢量数据,压缩方法 引言:矢量数据结构中,传统的方法是几何图形及其关系用文件方式组织,而属性数据通常采用关系型表文件记录,两者通过实体标识符连接。由于这一特点使得在某些方面有便利和独到之处,例如在计算长度、面积、形状和图形编辑、几何变换操作中,有很高的效率和精度。

矢量空间数据压缩 GIS中的矢量数据可分为点状图形要素、线状图形要素、面状图形要素。但从压缩的角度来看,矢量数据的压缩主要是线状图形要素的压缩,因为点状图形要素可看成是特殊的线状图形要素,面状图形要素的基础也是线状图形要素,需要由一条或多条线状图形要素围成。因此,线状图形要素的压缩就成为矢量数据压缩中最重要的问题。 矢量数据压缩是从组成曲线的点集合A中抽取一个子集B,用这个子集B在一定的精度范围内尽可能地反映原数据集合A,而这个子集B 的点数应尽可能少。矢量数据压缩与化简的核心是在不扰乱拓扑关系的前提下对原始采样数据进行合理的删减。 对矢量数据进行压缩除了能节约存贮空间,加快网络传输速度之外,其本质的原因在于原始的数据存在一定的冗余。这种数据冗余一方面是数据采样过程中不可避免产生的;另一方面是由于具体应用变化而产生,比如大比例尺的矢量数据用于小比例尺的应用时,就会存在不必要的数据冗余。因此应该根据具体应用来选择合适的矢量数据压缩与化简算法。 2、矢量数据压缩率与压缩误差 压缩率和压缩误差是评价一个矢量数据压缩算法的基本要素。分别以N和n表示矢量数据压缩前后的结点数。矢量数据压缩率为压缩后点的数量与压缩前点的数量之比,即η= (N-n) / N * 100%。 目前,描述压缩误差的方法主要有三种,分别是最大位移距离、位移距离之和以及偏差面积。假设压缩前的曲线为Fs,…,Ft,压缩后的线

图像压缩实验报告

竭诚为您提供优质文档/双击可除 图像压缩实验报告 篇一:实验三图像压缩 实验三图像压缩 一、实验目的 1.理解有损压缩和无损压缩的概念; 2.理解图像压缩的主要原则和目的; 3.了解几种常用的图像压缩编码方式。 4.利用mATLAb程序进行图像压缩。 二、实验仪器 1计算机; 2mATLAb等程序; 3移动式存储器(软盘、u盘等)。 4记录用的笔、纸。 三、实验原理 1.图像压缩原理 图像压缩主要目的是为了节省存储空间,增加传输速度。图像压缩的理想标准是信息丢失最少,压缩比例最大。不损

失图像质量的压缩称为无损压缩,无损压缩不可能达到很高的压缩比;损失图像质量的压缩称为有损压缩,高的压缩比是以牺牲图像质量为代价的。压缩的实现方法是对图像重新进行编码,希望用更少的数据表示图像。 信息的冗余量有许多种,如空间冗余,时间冗余,结构冗余,知识冗余,视觉冗余等,数据压缩实质上是减少这些冗余量。高效编码的主要方法是尽可能去除图像中的冗余成分,从而以最小的码元包含最大的图像信息。 编码压缩方法有许多种,从不同的角度出发有不同的分类方法,从信息论角度出发可分为两大类。 (1).冗余度压缩方法,也称无损压缩、信息保持编码或嫡编码。具体说就是解码图像和压缩编码前的图像严格相同,没有失真,从数学上讲是一种可逆运算。 (2)信息量压缩方法,也称有损压缩、失真度编码或烟压缩编码。也就是说解码图像和原始图像是有差别的,允许有一定的失真。 应用在多媒体中的图像压缩编码方法,从压缩编码算法原理上可以分为以下3类: (1)无损压缩编码种类 哈夫曼(huffman)编码,算术编码,行程(RLe)编码,Lempelzev编码。 (2)有损压缩编码种类

图像压缩算法的分析与研究本科毕业设计论文

图像压缩算法的分析与研究本科毕业设计论文 河南理工大学 本科毕业设计 图像压缩算法的分析与研究 摘? 要 随着多媒体技术和通讯技术的不断发展, 多媒体娱乐、信息高速公路等不断对信息数据的存储和传输提出了更高的要求, 也给现有的有限带宽以严峻的考验, 特别是具有庞大数据量的数字图像通信, 更难以传输和存储, 极大地制约了图像通信的发展, 因此图像压缩技术受到了越来越多的关注。图像压缩的目的就是把原来较大的图像用尽量少的字节表示和传输,并且要求复原图像有较好的质量。利用图像压缩, 可以减轻图像存储和传输的负担, 使图像在网络上实现快速传输和实时处理。 本文主要介绍数字图像处理的发展概况,图像压缩处理的原理和特点,对多种压缩编码方法进行描述和比较,详细讨论了Huffman编码的图像压缩处理的原理和应用。 关键词:图像处理,图像压缩,压缩算法,图像编码,霍夫曼编码

Abstract With the developing of multimedia technology and communication technology, multimedia entertainment, information, information highway have kept on data storage and transmission put forward higher requirements, but also to the limited bandwidth available to a severe test, especially with large data amount of digital image communication, more difficult to transport and storage, greatly restricted the development of image communication, image compression techniques are therefore more and more attention. The purpose of image compression is to exhaust the original image less the larger the bytes and transmission, and requires better quality of reconstructed images. Use of image compression, image storage

五种大数据压缩算法

?哈弗曼编码 A method for the construction of minimum-re-dundancy codes, 耿国华1数据结构1北京:高等教育出版社,2005:182—190 严蔚敏,吴伟民.数据结构(C语言版)[M].北京:清华大学出版社,1997. 冯桂,林其伟,陈东华.信息论与编码技术[M].北京:清华大学出版社,2007. 刘大有,唐海鹰,孙舒杨,等.数据结构[M].北京:高等教育出版社,2001 ?压缩实现 速度要求 为了让它(huffman.cpp)快速运行,同时不使用任何动态库,比如STL或者MFC。它压缩1M数据少于100ms(P3处理器,主频1G)。 压缩过程 压缩代码非常简单,首先用ASCII值初始化511个哈夫曼节点: CHuffmanNode nodes[511]; for(int nCount = 0; nCount < 256; nCount++) nodes[nCount].byAscii = nCount; 其次,计算在输入缓冲区数据中,每个ASCII码出现的频率: for(nCount = 0; nCount < nSrcLen; nCount++) nodes[pSrc[nCount]].nFrequency++; 然后,根据频率进行排序: qsort(nodes, 256, sizeof(CHuffmanNode), frequencyCompare); 哈夫曼树,获取每个ASCII码对应的位序列: int nNodeCount = GetHuffmanTree(nodes); 构造哈夫曼树 构造哈夫曼树非常简单,将所有的节点放到一个队列中,用一个节点替换两个频率最低的节点,新节点的频率就是这两个节点的频率之和。这样,新节点就是两个被替换节点的父

压缩技术实验编码

压缩技术实验编码 实验一统计编码 实验目的 1.熟悉统计编码的原理 2.掌握r元Huffman编码的方法; 3.了解Huffman编码效率及冗余度的计算; 二、实验原理 霍夫曼编码,又称最佳编码,根据字符出现概率来构造平均长度最短的变长编码。 Huffman编码步骤: (1)把信源符号x i(i=1,2,…按出现概率的值由大到小的顺序排列; (2)对两个概率最 小的符号分别分配以“ 0和“ 1,'然

后把这两个概率相加作为一个新的辅助符号的概率; (3)将这个新的辅助符号与其他符号一起重新按概率大小顺序排列; ⑷跳到第2步,直到出现概率相加为1为止; (5)用线将符号连接起来,从而得到一个码树,树的N个端点对应N个信源符号; (6)从最后一个概率为1的节点开始,沿着到达信源的每个符号,将一路遇到的二进制码“ 0或“ 1顺序排列起来,就是端点所对应的信源符号的码字。 以上是二元霍夫曼编码。如果是r元霍夫曼编码,则应该如何做呢? 在HUFFMAN 编码方案中,为出现概率较小的信源输出分配较长的码字,而对那些出现可能性较大的信源输出分配较短的码字。为此,首先将r 个最小可能的信源输出合并成为一个新的输出,该输出的概率就是上述的r 个输出的概率之和。重复进行该过程直到只剩下一个输出为止。信源符号的个数q 与r 必须满足如下的关系式: q = (r-1) n + r n 为整数如果不满足上述关系式,可通过添加概率为零的信源符号来满足。这样就生成了一个树,从该树的根节点出发并将0、1 分别分配给任何r 个来自于相同节点的 分支,生成编码。可以证明用这种方法产生的编码在前向树类

图像压缩算法论文

算法论文 基于huffman编码的图像压缩技术 姓名:康凯 学院:计算机学院 专业:网络工程1102 学号:201126680208 摘要 随着多媒体技术和通讯技术的不断发展, 多媒体娱乐、信息高速公路等不断对信息数据的存储和传输提出了更高的要求, 也给现有的有限带宽以严峻的考验, 特别是具有庞大数据量的数字图像通信, 更难以传输和存储, 极大地制约了图像通信的发展, 因此图像压缩技术受到了越来越多的关注。图像压缩的目的就是把原来较大的图像用尽量少的字节表示和传输,并且要求复原图像有较好的质量。利用图像压缩, 可以减轻图像存储和传输的负担, 使图像在网络上实现快速传输和实时处理。 本文主要介绍数字图像处理的发展概况,图像压缩处理的原理和特点,对多种压缩编码方法进行描述和比较,详细讨论了Huffman编码的图像压缩处理的原理和应用。 关键词:图像处理,图像压缩,压缩算法,图像编码,霍夫曼编码 Abstract With the developing of multimedia technology and communication technology, multimedia entertainment, information, information highway have kept on data storage and transmission put forward higher requirements, but also to the limited bandwidth available to a severe test, especially with large data amount of digital image communication, more difficult to transport and storage, greatly restricted the development of image communication, image compression techniques are therefore more and more attention. The purpose of image compression is to exhaust the original image less the larger the bytes and transmission, and requires better quality of

图像压缩算法性能的测试与分析工具

图像压缩算法性能的测试与分析工具1 蔡正兴,张虹 中国矿业大学计算机科学与技术学院,江苏徐州 (221008) 摘要:本文研究了图像压缩算法性能的评价方法,提出了图像压缩算法性能的测试算法,包括横向比较测试和纵向分解测试,并在此基础上设计并实现了压缩算法性能的测试与分析工具。该工具能够测试和分析压缩算法的性能,并自动生成各种分析图表,为用户提供了方便,具有较大的实用价值。为了提高评价的效率、准确性和全面性,文中提出了测试图像的选择方法和测试结果的分析方法,具有一定的理论意义。 关键词:压缩性能,测试方法,分析方法,图像选择方法 1. 引言 近年来,图像压缩得到快速发展[1],各种算法层出不穷,比如有损的压缩算法可以在低失真的条件下达到高压缩比[2,3],而无损的压缩算法则可以保证重建图像的无失真[4]。因此在实际应用中得知各种压缩算法的性能及特点是必要的。在评价图像压缩算法性能时主要考虑压缩比、重建质量、时间复杂度、空间复杂度和实现代价这几个方面[5],其中较为重要的是压缩比、重建质量和时间复杂度。为了计算这些压缩性能指标,常常使用一些工具软件,比如在图像处理领域广泛使用的MATLAB系列软件,它提供了大量的内置函数[6],操作方便,功能强大,但它不是评价图像压缩算法性能的专业工具,需要进行二次开发,不能有效的分析和评价压缩性能。其次,利用性能指标来评价压缩方法,尽管方便快捷,但还不能反映图像压缩算法的全部特点。例如,在考虑变换编码系统的失真性质时,一般采用MSE(均方误差),有时利用MSE计算得到的重建质量很好,但视觉效果却不好,这是因为MSE对图像中的失真显著性不敏感[7],可见,性能指标仅仅是对压缩算法进行宏观上的评价,无法评价每个过程对压缩性能的影响。再次,在评价压缩性能时,不可避免地要使用测试图像,用户在选择测试图像时带有随机性,不利于全面地评价压缩方法。针对这些不足,本文设计了图像压缩算法性能的测试与分析工具——AutoTA。AutoTA的目标是自动地对图像压缩算法进行测试与分析,并生成各种分析图表,全面的评价图像压缩算法的性能。AutoTA具有广泛的应用前景,科研人员利用AutoTA可横向比较各种压缩算法的性能,也可纵向分析压缩算法的特点;工程技术人员也可以根据AutoTA的测试结果,在实际应用中选择合适的图像压缩算法。 2. 压缩算法性能指标 压缩性能指标是评价压缩算法的重要方面,也是AutoTA分析图像压缩算法性能的重要依据,下面将描述相关的性能指标。 2.1压缩比 压缩比是指压缩过程中输入数据量和输出数据量之比,反映了图像压缩算法的压缩性能,当压缩比小于1时为正压缩,当压缩比大于1时为负压缩。压缩比的计算公式为: 1本课题得到国家自然科学基金项目(编号:60372102)、教育部博士点基金项目(编号:20030290011)、软件新技术国家重点实验室课题(编号:A200309)资助。

LZ77压缩算法实验报告

LZ77压缩算法实验报告 一、实验内容 使用C++编程实现LZ77压缩算法的实现。 二、实验目的 用LZ77实现文件的压缩。 三、实验环境 1、软件环境:Visual C++ 6.0 2、编程语言:C++ 四、实验原理 LZ77 算法在某种意义上又可以称为“滑动窗口压缩”,这是由于该算法将一个虚拟的,可以跟随压缩进程滑动的窗口作为术语字典,要压缩的字符串如果在该窗口中出现,则输出其出现位置和长度。使用固定大小窗口进行术语匹配,而不是在所有已经编码的信息中匹配,是因为匹配算法的时间消耗往往很多,必须限制字典的大小才能保证算法的效率;随着压缩的进程滑动字典窗口,使其中总包含最近编码过的信息,是因为对大多数信息而言,要编码的字符串往往在最近的上下文中更容易找到匹配串。 五、LZ77算法的基本流程 1、从当前压缩位置开始,考察未编码的数据,并试图在滑动窗口中找出最长的匹 配字符串,如果找到,则进行步骤2,否则进行步骤3。 2、输出三元符号组( off, len, c )。其中off 为窗口中匹

配字符串相对窗口边 界的偏移,len 为可匹配的长度,c 为下一个字符。然后将窗口向后滑动len + 1 个字符,继续步骤1。 3、输出三元符号组( 0, 0, c )。其中c 为下一个字符。然后将窗口向后滑动 len + 1 个字符,继续步骤1。 六、源程序 /********************************************************************* * * Project description: * Lz77 compression/decompression algorithm. * *********************************************************************/ #include #include #include #include #define OFFSET_CODING_LENGTH (10) #define MAX_WND_SIZE 1024 //#define MAX_WND_SIZE (1<

图像压缩实验指导书

数字图像处理上机实验指导书 童立靖

北方工业大学计算机学院

实验四图像压缩 一、实验目的、要求与环境 目的: 通过实验,了解数字图象压缩的一般方法,掌握图像压缩的编程方法,了解图象压缩效果的评价方法。 1.2要求: 对自选的图象进行离散余弦变换,将其进行图象压缩处理,自行设计量化矩阵,与编码方法,并计算压缩比,提交实验报告。 进度较快的同学,可以设计三种不同的量化矩阵或编码方法,完成三种不同程度的压缩,对比解压缩后的图像质量,并进行分析。(给分较高) 环境: Windows XP操作系统 Microsoft Visual C++ (SP6) 自带8位灰度图像文件: : 3

二、实验步骤 1.准备相关图像文件。 2.在XP操作系统上,打开Microsoft Visual C++ (SP6),编写相关程序,完成对离散余弦变换系数的量化矩阵设计与编码方法。 4.对程序进行相关调试,修改程序,去除其中的BUG。 5. 利用自己准备的图像的文件,和编写的程序,将给定的图象进行压缩处理。 6.截屏,保留实验结果。 7. 计算压缩比, 进行实验结果分析。 8. 撰写并提交实验报告。 三、注意事项 1.实验任务: Windows下完成图像压缩的程序编写。 2.去多模式教学网上下载程序框架: 。 3.图像高度、宽度须是8的倍数。BMP 格式,8位灰度图像。 4.对于一幅彩色图像,可以在photoshop中,图像=》模式=》灰度=》扔掉 文件=》存储为=》保存=》选择8位深度=》确定。 5.实验完成时间: 先在课下完成程序编写,然后课上完成验机。 第15周的周一、第15周的周五,二次实验课。 6.请记录实验报告中相应的贴图: 可以用屏幕拷贝,然后再用Photoshop中的工具中修剪一下。 7.请每位同学用自己的图像文件进行实验: 若2位同学使用的图像文件一样,两位均依抄袭计0分。 8.请每位同学自己编写程序:

JPEG图像压缩算法及其实现

多媒体技术及应用 JPEG图像压缩算法及其实现 罗群书 0411102班 2011211684

一、JEPG压缩算法(标准) (一)JPEG压缩标准 JPEG(Joint Photographic Experts Group)是一个由ISO/IEC JTC1/SC2/WG8和CCITT VIII/NIC于1986年底联合组成的一个专家组,负责制定静态的数字图像数据压缩编码标准。迄今为止,该组织已经指定了3个静止图像编码标准,分别为JPEG、JPEG-LS和JPEG2000。这个专家组于1991年前后指定完毕第一个静止图像压缩标准JPEG标准,并且成为国际上通用的标准。JPEG标准是一个适用范围很广的静态图像数据压缩标准,既可用于灰度图像又可用于彩色图像。 JPEG专家组开发了两种基本的静止图像压缩算法,一种是采用以离散余弦变换(Discrete Cosine Transform, DCT)为基础的有损压缩算法,另一种是采用以预测技术为基础的无损压缩算法。使用无损压缩算法时,其压缩比比较低,但可保证图像不失真。使用有损压缩算法时,其算法实现较为复杂,但其压缩比大,按25:1压缩后还原得到的图像与原始图像相比较,非图像专家难于找出它们之间的区别,因此得到了广泛的应用。 JPEG有4种工作模式,分别为顺序编码,渐近编码,无失真编码和分层编码,他们有各自的应用场合,其中基于顺序编码工作模式的JPEG压缩系统也称为基本系统,该系统采用单遍扫描完成一个图像分量的编码,扫描次序从左到右、从上到下,基本系统要求图像像素的各个色彩分量都是8bit,并可通过量化线性地改变DCT系统的量化结果来调整图像质量和压缩比。下面介绍图像压缩采用基于DCT的顺序模式有损压缩算法,该算法下的JPEG压缩为基本系统。 (二)JPEG压缩基本系统编码器 JPEG压缩是有损压缩,它利用了人的视觉系统的特性,将量化和无损压缩编码相结合来去掉视觉的冗余信息和数据本身的冗余信息。基于基本系统的JPEG压缩编码器框图如图1所示,该编码器是对单个图像分量的处理,对于多个分量的图像,则首先应将图像多分量按照一定顺序和比例组成若干个最小压缩单元(MCU),然后同样按该编码器对每个MCU各个分量进行独立编码处理,最终图像压缩数据将由多个MCU压缩数据组成。 图1 JPEG压缩编码器结构框图

几种视频压缩算法对比

视频压缩算法对比 视频2008-05-23 10:10:09 阅读557 评论0 字号:大中小订阅 视频压缩标准及比较原始的数字视频信号的数据量是相当惊人的,例如,NTSC 图像以大约640X480的分辨率,24bist/象素,每秒30帧的质量传输时,则视频数据有640X480x24X30=221Mb/S或28MB/s秒,显然这样庞大的数据流对大多数传输线路来说是无法承受的,而且也是无法存储的。为此人们开始专门研究将这些视频、音频数据流进行压缩。很多压缩编码标准相继推出,主要有JPEG月吐一JPEG‘,幻,_H.261旧.263和MPEG等标准。其中JPEG标准主要是用在静止图像的压缩。M一PJEG是将PJEG改进后用到运动图像上,在压缩比不高时,有较好的复现图像质量,但占用存储空间大;在压缩比高的情况下,复现图像质量差。.H261爪.263标准是专门为用于图像质量要求不高的视频会议和可视电话设计。MpEG(MovnigPictureExPertGorPu即活动图像专家组)。它是由150(国际标准化组织)和正(c国际电工委员会)于1988年联合成立的。专门致力于运动图像及伴音编码标准化工作。它们推出了MPEG编码标准【1卜,1l。到现在为止,专家组己制定了MPEG一1,MPEG一2和MPEG一4三种标准,由于其标准化、较大的压缩比及较高的画面质量,成为视频压缩系统首选算法。 MPEGI是一种压缩比高但图像质量稍差的技术;而MPEGZ技术主要专注于图像质量,压缩比小,因此需要的存储空间就大;MPEG4技术是时下比较流行的技术,使用这种技术可以节省空间、提高图像质量、节省网络传输带宽等优点。 来自:https://www.doczj.com/doc/5d8220191.html,/blog/static/80720305200842310109120/

LZSS压缩算法实验报告

实验名称:LZSS压缩算法实验报告 一、实验内容 使用Visual 6..0 C++编程实现LZ77压缩算法。 二、实验目的 用LZSS实现文件的压缩。 三、实验原理 LZSS压缩算法是词典编码无损压缩技术的一种。LZSS压缩算法的字典模型使用了自适应的方式,也就是说,将已经编码过的信息作为字典, 四、实验环境 1、软件环境:Visual C++ 6.0 2、编程语言:C++ 五、实验代码 #include #include #include #include /* size of ring buffer */ #define N 4096 /* index for root of binary search trees */ #define NIL N /* upper limit for g_match_len. Changed from 18 to 16 for binary compatability with Microsoft COMPRESS.EXE and EXPAND.EXE #define F 18 */ #define F 16 /* encode string into position and length if match_length is greater than this: */ #define THRESHOLD 2 /* these assume little-endian CPU like Intel x86

-- need byte-swap function for big endian CPU */ #define READ_LE32(X) *(uint32_t *)(X) #define WRITE_LE32(X,Y) *(uint32_t *)(X) = (Y) /* this assumes sizeof(long)==4 */ typedef unsigned long uint32_t; /* text (input) size counter, code (output) size counter, and counter for reporting progress every 1K bytes */ static unsigned long g_text_size, g_code_size, g_print_count; /* ring buffer of size N, with extra F-1 bytes to facilitate string comparison */ static unsigned char g_ring_buffer[N + F - 1]; /* position and length of longest match; set by insert_node() */ static unsigned g_match_pos, g_match_len; /* left & right children & parent -- these constitute binary search tree */ static unsigned g_left_child[N + 1], g_right_child[N + 257], g_parent[N + 1]; /* input & output files */ static FILE *g_infile, *g_outfile; /***************************************************************************** initialize trees *****************************************************************************/ static void init_tree(void) { unsigned i; /* For i = 0 to N - 1, g_right_child[i] and g_left_child[i] will be the right and left children of node i. These nodes need not be initialized. Also, g_parent[i] is the parent of node i. These are initialized to NIL (= N), which stands for 'not used.' For i = 0 to 255, g_right_child[N + i + 1] is the root of the tree for strings that begin with character i. These are initialized to NIL. Note there are 256 trees. */ for(i = N + 1; i <= N + 256; i++) g_right_child[i] = NIL; for(i = 0; i < N; i++) g_parent[i] = NIL; } /***************************************************************************** Inserts string of length F, g_ring_buffer[r..r+F-1], into one of the trees (g_ring_buffer[r]'th tree) and returns the longest-match position and length via the global variables g_match_pos and g_match_len. If g_match_len = F, then removes the old node in favor of the new one, because the old one will be deleted sooner.

游程编码实验报告

重庆交通大学信息科学与工程学院综合性设计性实验报告 专业:通信工程专业11级 学号:631106040222 姓名:徐国健 实验所属课程:移动通信原理与应用 实验室(中心):信息技术软件实验室 指导教师:李益才 2014年5月

一、题目 二值图像的游程编码及解码 二、仿真要求 对一幅图像进行编码压缩,然后解码恢复图像。 三、仿真方案详细设计 实验过程分为四步:分别是读入一副图象,将它转换成为二进制灰度图像,然后对其进行游程编码和压缩,最后恢复图象(只能恢复为二值图像)。 1、二值转换 所谓二值图像,就是指图像上的所有像素点的灰度值只用两种可能,不为“0”就为“1”,也就是整个图像呈现出明显的黑白效果。 2、游程编码原理 游程编码是一种无损压缩编码,对于二值图有效。游程编码的基本原理是:用一个符号值或串长代替具有相同值的连续符号,使符号长度少于原始数据的长度。据进行编码时,沿一定方向排列的具有相同灰度值的像素可看成是连续符号,用字串代替这些连续符号,可大幅度减少数据量。游程编码分为定长行程编码和不定长行程编码两种类型。游程编码是连续精确的编码,在传输过程中,如果其中一位符号发生错误,即可影响整个编码序列,使行程编码无法还原回原始数据。 3、游程编码算法 一般游程编码有两种算法,一种是使用1的起始位置和1的游程长度,另一种是只使用游程长度,如果第一个编码值为0,则表示游程长度编码是从0像素的长度开始。这次实验采

用的是前一种算法。两种方法各有优缺点:前一种存储比第二种困难,因此编程也比较复杂。而后一种需要知道第一个像素值,故压缩编码算法中需给出所读出的图的第一个像素值。 压缩流程图: 解压流程图:

JPEG2000图像压缩算法标准剖析

JPEG2000图像压缩算法标准 摘要:JPEG2000是为适应不断发展的图像压缩应用而出现的新的静止图像压缩标准。本文介绍了JPEG2000图像编码系统的实现过程, 对其中采用的基本算法和关键技术进行了描述,介绍了这一新标准的特点及应用场合,并对其性能进行了分析。 关键词:JPEG2000;图像压缩;基本原理;感兴趣区域 引言 随着多媒体技术的不断运用,图像压缩要求更高的性能和新的特征。为了满足静止图像在特殊领域编码的需求,JPEG2000作为一个新的标准处于不断的发展中。它不仅希望提供优于现行标准的失真率和个人图像压缩性能,而且还可以提供一些现行标准不能有效地实现甚至在很多情况下完全无法实现的功能和特性。这种新的标准更加注重图像的可伸缩表述。所以就可以在任意给定的分辨率级别上来提供一个低质量的图像恢复,或者在要求的分辨率和信噪比的情况下提取图像的部分区域。 1.JPEG2000的基本介绍及优势 相信大家对JPEG这种图像格式都非常熟悉,在我们日常所接触的图像中,绝大多数都是JPEG格式的。JPEG的全称为Joint Photographic Experts Group,它是一个在国际标准组织(ISO)下从事静态图像压缩标准制定的委员会,它制定出了第一套国际静态图像压缩标准:ISO 10918-1,俗称JPEG。由于相对于BMP等格式而言,品质相差无己的JPEG格式能让图像文件“苗条”很多,无论是传送还是保存都非常方便,因此JPEG格式在推出后大受欢迎。随着网络的发展,JPEG的应用更加广泛,目前网站上80%的图像都采用JPEG格式。 但是,随着多媒体应用领域的快速增长,传统JPEG压缩技术已无法满足人们对数字化多媒体图像资料的要求:网上JPEG图像只能一行一行地下载,直到全部下载完毕,才可以看到整个图像,如果只对图像的局部感兴趣也只能将整个图片载下来再处理;JPEG格式的图像文件体积仍然嫌大;JPEG格式属于有损压缩,当被压缩的图像上有大片近似颜色时,会出现马赛克现象;同样由于有损压缩的原因,许多对图像质量要求较高的应用JPEG无法胜任。 JPEG2000是为21世纪准备的压缩标准,它采用改进的压缩技术来提供更高的解像度,其伸缩能力可以为一个文件提供从无损到有损的多种画质和解像选择。JPEG2000被认为是互联网和无线接入应用的理想影像编码解决方案。 “高压缩、低比特速率”是JPEG2000的目标。在压缩率相同的情况下,JPEG2000的信噪比将比JPEG提高30%左右。JPEG2000拥有5种层次的编码形式:彩色静态画面采用的JPEG 编码、2值图像采用的JBIG、低压缩率图像采用JPEGLS等,成为应对各种图像的通用编码方式。在编码算法上,JPEG2000采用离散小波变换(DWT)和bit plain算术编码(MQ coder)。此外,JPEG2000还能根据用户的线路速度以及利用方式(是在个人电脑上观看还是在PDA上观看),以不同的分辨率及压缩率发送图像。 JPEG2000的制定始于1997年3月,但因为无法很快确定算法,因此耽误了不少时间,直到2000年 3 月,规定基本编码系统的最终协议草案才出台。目前JPEG2000已由ISO和

无损压缩算法的比较和分析

Adaptive-Huffman-Coding 自适应霍夫曼编码 压缩比:1.79 分析: 霍夫曼算法需要有关信息源的先验统计知识,而这样的信息通常很难获得,即使能够获得这些统计数字,符号表的传输仍然是一笔相当大的开销。 自适应压缩算法能够解决上述问题,统计数字是随着数据流的到达而动态地收集和更新的。概率再不是基于先验知识而是基于到目前为止实际收到的数据。随着接收到的符号的概率分布的改变,符号将会被赋予新的码字,这在统计数字快速变化的多媒体数据中尤为适用。 Lempel-Ziv-Welch 基于字典的编码 压缩比:1.86 分析: LZW算法利用了一种自适应的,基于字典的压缩技术。和变长编码方式不同,LZW使用定长的码字(本次实验使用12位定长码字)来表示通常会在一起出现的符号/字符的变长的字符串。 LZW编码器和解码器会在接受数据是动态的创建字典,编码器和解码器也会产生相同的字典。 编码器的动作有时会先于解码器发生。因为这是一个顺序过程,所以从某种意义上说,这是可以预见的。

算术编码(arithmetic coding) 压缩比:2 分析: 算术编码是一种更现代化的编码方法,在实际中不赫夫曼编码更有效。 算术编码把整个信息看作一个单元,在实际中,输入数据通常被分割成块以免错误传播。 算术编码将整个要编码的数据映射到一个位于[0,1)的实数区间中。并且输出一个小于1同时大于0的小数来表示全部数据。利用这种方法算术编码可以让压缩率无限的接近数据的熵值,从而获得理论上的最高压缩率。 比较分析: 一般来说,算术编码的性能优于赫夫曼编码,因为前者将整个消息看作一个单元,而后者受到了必须为每一个符号分配整数位的限制。 但是,算术编码要求进行无限精度的实数运算,这在仅能进行有限精度运算的计算机系统是无法进行的。随着研究的深入,有学者提出了一种基于整数运算的算术编码实现算法。在编码和解码的过程还需要不时的调整区间大小,以免精度不足,加大了实现的难度。 在3种无损压缩算法中,LZW算法相对来说,实现最为简单,但其压缩效果要在数据源足够大的时候,才能显现出来。

多媒体数据压缩实验报告

多媒体数据压缩实验报告 篇一:多媒体实验报告_文件压缩 课程设计报告 实验题目:文件压缩程序 姓名:指导教师:学院:计算机学院专业:计算机科学与技术学号: 提交报告时间:20年月日 四川大学 一,需求分析: 有两种形式的重复存在于计算机数据中,文件压缩程序就是对这两种重复进行了压 缩。 一种是短语形式的重复,即三个字节以上的重复,对于这种重复,压缩程序用两个数字:1.重复位置距当前压缩位置的距离;2.重复的长度,来表示这个重复,假设这两个数字各占一个字节,于是数据便得到了压缩。 第二种重复为单字节的重复,一个字节只有256种可能的取值,所以这种重复是必然的。给 256 种字节取值重新编码,使出现较多的字节使用较短的编码,出现较少的字节使用较长的编码,这样一来,变短的字节相对于变长的字节更多,文件的总长度就会减少,并且,字节使用比例越不均

匀,压缩比例就越大。 编码式压缩必须在短语式压缩之后进行,因为编码式压缩后,原先八位二进制值的字节就被破坏了,这样文件中短语式重复的倾向也会被破坏(除非先进行解码)。另外,短语式压缩后的结果:那些剩下的未被匹配的单、双字节和得到匹配的距离、长度值仍然具有取值分布不均匀性,因此,两种压缩方式的顺序不能变。 本程序设计只做了编码式压缩,采用Huffman编码进行压缩和解压缩。Huffman编码是一种可变长编码方式,是二叉树的一种特殊转化形式。编码的原理是:将使用次数多的代码转换成长度较短的代码,而使用次数少的可以使用较长的编码,并且保持编码的唯一可解性。根据 ascii 码文件中各 ascii 字符出现的频率情况创建 Huffman 树,再将各字符对应的哈夫曼编码写入文件中。同时,亦可根据对应的哈夫曼树,将哈夫曼编码文件解压成字符文件. 一、概要设计: 压缩过程的实现: 压缩过程的流程是清晰而简单的: 1. 创建 Huffman 树 2. 打开需压缩文件 3. 将需压缩文件中的每个 ascii 码对应的 huffman 编码按 bit 单位输出生成压缩文件压缩结束。

图像压缩编码实验报告

图像压缩编码实验报告 一、实验目的 1.了解有关数字图像压缩的基本概念,了解几种常用的图像压缩编码方式; 2.进一步熟悉JPEG编码与离散余弦变换(DCT)变换的原理及含义; 3.掌握编程实现离散余弦变换(DCT)变换及JPEG编码的方法; 4.对重建图像的质量进行评价。 二、实验原理 1、图像压缩基本概念及原理 图像压缩主要目的是为了节省存储空间,增加传输速度。图像压缩的理想标准是信息丢失最少,压缩比例最大。不损失图像质量的压缩称为无损压缩,无损压缩不可能达到很高的压缩比;损失图像质量的压缩称为有损压缩,高的压缩比是以牺牲图像质量为代价的。压缩的实现方法是对图像重新进行编码,希望用更少的数据表示图像。应用在多媒体中的图像压缩编码方法,从压缩编码算法原理上可以分为以下3类: (1)无损压缩编码种类 哈夫曼(Huffman)编码,算术编码,行程(RLE)编码,Lempel zev编码。(2)有损压缩编码种类 预测编码,DPCM,运动补偿; 频率域方法:正交变换编码(如DCT),子带编码; 空间域方法:统计分块编码; 模型方法:分形编码,模型基编码; 基于重要性:滤波,子采样,比特分配,向量量化; (3)混合编码 JBIG,H.261,JPEG,MPEG等技术标准。 2、JPEG 压缩编码原理 JPEG是一个应用广泛的静态图像数据压缩标准,其中包含两种压缩算法(DCT和DPCM),并考虑了人眼的视觉特性,在量化和无损压缩编码方面综合权衡,达到较大的压缩比(25:1以上)。JPEG既适用于灰度图像也适用于彩色图像。其中最常用的是基于DCT变换的顺序式模式,又称为基本系统。JPEG 的压缩编码大致分

图像压缩算法

《算法设计与分析》课程报告 姓名:文亮 学号:201322220254 学院:信息与软件工程学院 老师:屈老师;王老师

算法实现与应用——《算法设计与分析》课程报告 一. 基本要求 1. 题目: 图像压缩 2. 问题描述 掌握基于DCT 变换的图像压缩的基本原理及其实现步骤;对同一幅原 始图像进行压缩,进一步掌握DCT 和图像压缩。 3. 算法基本思想 图像数据压缩的目的是在满足一定图像质量的条件下,用尽可能少的比特数来表示原始图像,以提高图像传输的效率和减少图像存储的容量,在信息论中称为信源编码。图像压缩是通过删除图像数据中冗余的或者不必要的部分来减小图像数据量的技术,压缩过程就是编码过程,解压缩过程就是解码过程。压缩技术分为无损压缩和有损压缩两大类,前者在解码时可以精确地恢复原图像,没有任何损失;后者在解码时只能近似原图像,不能无失真地恢复原图像。 假设有一个无记忆的信源,它产生的消息为{}N ≤≤i a i 1,其出现的概率是已知的,记为()i a p 。则其信息量定义为: ()()i i a p a log -=I 由此可见一个消息出现的可能性越小,其信息量就越多,其出现对信息的贡献量越大,反之亦然。 信源的平均信息量称为“熵”(entropy ),可以表示为: ()()[]()()∑∑==-=?=H N i i i N i i i a p a p a p I a p 1 1 log 对上式取以2为底的对数时,单位为比特(bits ): ()()∑=-=H N i i i a p a p 1log 根据香农(Shannon )无噪声编码定理,对于熵为H 的信号源,对其进行无

相关主题
文本预览
相关文档 最新文档