7-10 lzw.c

 #include <stdlib.h>
 #include <stdio.h>
 #define BITS 12 //每个数据项的二进制位数
 #define HASHING_SHIFT BITS-8 //HASH表的移位数
 #define MAX_VALUE (1<<BITS)-1
 #define MAX_CODE MAX_VALUE-1 //最大标号
 #define TABLE_SIZE 4099 //HASH表的长度
 typedef struct{
     int *code;    //代码
     unsigned int *prefix; //前缀
     unsigned char *suffix; //后缀
 }LZW_DATA;
 unsigned char decode_stack[TABLE_SIZE]; //用于保存解压缩后的数据
 LZW_DATA lzw1,*lzw;

 void compress(FILE *input,FILE *output); //压缩函数
 void expand(FILE *input,FILE *output); //解压函数
 unsigned int hashsearch(int hash_prefix,unsigned int hash_character); //HASH表搜索函数
 char *decode(unsigned char *buffer,unsigned int code);
 unsigned int incode(FILE *input);
 void outcode(FILE *output,unsigned int code);

 void compress(FILE *input,FILE *output) //压缩函数
 {
     unsigned int curr_code;
     unsigned int suffix;   //后缀字符
     unsigned int prefix;   //前缀字符
     unsigned int index;
     int i;

     if(!(lzw1.code=malloc(TABLE_SIZE*sizeof(unsigned int)))) //代码值数组
     {
         printf("内存分配失败!\n");
         exit();
     }
     if(!(lzw1.prefix=malloc(TABLE_SIZE*sizeof(unsigned int))))//压缩前数据
     {
         printf("内存分配失败!\n");
         exit();
     }
     if(!(lzw1.suffix=malloc(TABLE_SIZE*sizeof(unsigned char))))//压缩后数据
     {
         printf("内存分配失败!\n");
         exit();
     }
     lzw=&lzw1;
     curr_code=; //编译表中的字符串编号从258开始
     ;i<TABLE_SIZE;i++) //初始化标号数组
         lzw->code[i]=-;
     i=;
     printf("\n开始压缩.");
     prefix=getc(input); //从文件读取一个字节
     while((suffix=getc(input))!= (unsigned)EOF) //循环处理输入文件中的内容
     {
         ) //处理1000个字节显示一个小数点,表示系统正在处理
         {
             i=;
             printf(".");
         }
         index=hashsearch(prefix,suffix); //在HASH表中查找并返回索引号
         )//若该标号存在
             prefix=lzw->code[index];//使用该标号作为前缀
         else{                                            //若标号不存在
             if (curr_code<=(MAX_CODE)){ //标号未超过最大标号
                 lzw->code[index]=curr_code++; //增加一个标号
                 lzw->prefix[index]=prefix;  //保存前缀
                 lzw->suffix[index]=suffix; //保存后缀
             }
             outcode(output,prefix); //输出前缀字节的内容
             prefix=suffix;//将后缀作前缀,准备下次循环
         }
     }
     outcode(output,prefix); //输出前缀
     outcode(output,(MAX_VALUE)); //输出结束标志
     outcode(output,);   

     free(lzw->code); //释放分配的内存
     free(lzw->prefix);
     free(lzw->suffix);
 }

 unsigned int hashsearch(int prefix,unsigned int suffix)//HASH表搜索函数
 {
     int index;
     int offset;
     index=(suffix << HASHING_SHIFT)^prefix; //构造HASH地址
     )
         offset=;
     else
         offset=TABLE_SIZE-index;
     )
     {
         ) //找到一个空表项
             return(index); //返回HASH地址
         if (lzw->prefix[index]==prefix && lzw->suffix[index]==suffix) //找到目标数据
             return(index); //返回HASH地址
         index-=offset; //处理冲突,调整HASH地址
         ) index+=TABLE_SIZE; //调整HASH地址
     }
 }

 void outcode(FILE *output,unsigned int code) //输出压缩后的字节内容
 {
     ; //静态变量,保存已输出数据的二进制位数
     static unsigned long obb=0L;//静态变量,保存需输出数据的二进制位数
     obb |= (unsigned -BITS-ob); //进行移位合并
     ob+=BITS; //增加需输出数据的二进制位
     )  //达到一个字节,则输出
     {
         putc(obb>>,output); //右移24位,使低字节8位为需要输出的数据
         obb<<= ;  //左移8位,去掉已输入的一个字节数据
         ob-=;    //减去已输出的8位,保留剩余的未输出的位数
     }
     return;
 }
 void expand(FILE *input,FILE *output) //解压缩函数
 {
     unsigned int curr_code;
     unsigned int suffix;
     unsigned int prefix;
     int ch;
     int i;
     unsigned char *ps;
     char *decode(unsigned char *buffer,unsigned int code);

     if(!(lzw1.code=malloc(TABLE_SIZE*sizeof(unsigned int)))) //代码值数组
     {
         printf("内存分配失败!\n");
         exit();
     }
     if(!(lzw1.prefix=malloc(TABLE_SIZE*sizeof(unsigned int))))//压缩前数据
     {
         printf("内存分配失败!\n");
         exit();
     }
     if(!(lzw1.suffix=malloc(TABLE_SIZE*sizeof(unsigned char))))//压缩后数据
     {
         printf("内存分配失败!\n");
         exit();
     }
     lzw=&lzw1;
     curr_code=; //定义标号从258开始
     i=;
     printf("\n解压缩.");
     prefix=incode(input);  //读入第一个编码,并初始化字符变量
     ch=prefix; //保存前缀到字符变量
     putc(prefix,output);      // 输出字符到输出文件上
     while ((suffix=incode(input))!=(MAX_VALUE)) //循环进行解压缩
     {
         )    //处理1000个字节就显示一个点
         {
             i=;
             printf(".");
         }
         if (suffix>=curr_code)//后缀是未定义的标号
         {
             *decode_stack=ch; //保存前缀字符
             ps=decode(decode_stack+,prefix);//调用函数进行解码
         }
         else
             ps=decode(decode_stack,suffix); //调用解码函数处理后缀 

         ch=*ps;
         while(ps>=decode_stack) //循环输出解码的字节
             putc(*ps--,output);
         if (curr_code<=MAX_CODE) //若标号未超过最大值
         {
             lzw->prefix[curr_code]=prefix; //保存前缀到编译表
             lzw->suffix[curr_code]=ch;     //保存后缀到编译表
             curr_code++; //标号增加
         }
         prefix=suffix; //后缀作前缀,准备下次的循环
     }

     free(lzw->code); //释放分配的内存
     free(lzw->prefix);
     free(lzw->suffix);
 }
 char *decode(unsigned char *buffer,unsigned int code) //解码函数
 {
     ;
     ) //code不是ASCII码字符
     {
         *buffer++ =lzw->suffix[code]; //保存标号到缓冲区
         code=lzw->prefix[code]; //取得该标号的前缀
         if (i++>=TABLE_SIZE)
         {
             printf("内存溢出!\n");
             exit();
         }
     }
     *buffer=code; //将标号放入缓冲区
     return(buffer); //返回缓冲区中的内容
 }

 unsigned int incode(FILE *input) //从压缩文件中读取数据
 {
     unsigned int ret;
     ; //静态变量,保存读入数据的二进制位数
     static unsigned long ibb=0L; //静态变量,保存已读入数据的二进制位
     ) //若数据位数小于24位
     {
         ibb |= (unsigned -ib); //从文件中获取一个字节,并组合到需输出的二进制位中
         ib += ;
     }
     ret=ibb>>(-BITS); //右移20位二进制数 (32-12)
     ibb <<= BITS; //再左多12位
     ib -= BITS; //减去已返回的位数
     return(ret);//返回移位后的数据
 }
 int main(int argc, char *argv[])
 {
     FILE *fp1,*fp2;
     ;
     char *op;
     ) //判断传入参数的数量
         flag=;
     else{
         op=argv[];
         ) && strcmp(op,) flag=;
     }
     if(flag)
     {
         printf("使用方法:command -z/-e source dest\n");
         exit();
     }
     ],"rb"))==NULL) //打开文件出错
     {
         printf("不能打开源文件!\n");
         exit();
     }
     ],"wb"))==NULL) //创建文件出错
     {
         printf("不能创建目标文件!\n");
         exit();
     }
     )
         compress(fp1,fp2);//调用压缩函数
     else
         expand(fp1,fp2);//调用解压缩函数
     fclose(fp1);//释放文件指针
     fclose(fp2);
     ;
 }

7.8 LZW压缩的实现的更多相关文章

  1. LZW压缩算法

    转载自http://www.cnblogs.com/jillzhang/archive/2006/11/06/551298.html 记录此处仅自己供学习之用 lzw解压缩算法: 用单个字符初始化字符 ...

  2. 浓缩的才是精华:浅析GIF格式图片的存储和压缩

    成文迪, 在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦. GIF格式的历史 GIF(Graphics Interchange Format)原义是"图像互换 ...

  3. golang使用 gzip压缩

    golang使用 gzip压缩 这个例子中使用gzip压缩格式,标准库还支持zlib, bz2, flate, lzw 压缩处理_三步: 1.创建压缩文件2.gzip write包装3.写入数据 ou ...

  4. 【腾讯Bugly干货分享】舞动的表情包——浅析GIF格式图片的存储和压缩

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:https://mp.weixin.qq.com/s/v0pffOhjFWnVbU2lXjuEmw 导语 G ...

  5. 腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践

    本文来自腾讯前端开发工程师“ wendygogogo”的技术分享,作者自评:“在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦.” 1.GIF格式的历史 GIF ( Gr ...

  6. LZW算法PHP实现方法 lzw_decompress php

    LZW算法PHP实现方法 lzw_decompress php 博客分类: Php / Pear / Mysql / Node.js   LZW算法简介 字符串和编码的对应关系是在压缩过程中动态生成的 ...

  7. 黄聪:浓缩的才是精华:浅析GIF格式图片的存储和压缩(转)

    http://www.cnblogs.com/qcloud1001/p/6647080.html 成文迪, 在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦. GIF格式 ...

  8. 如何将matlab画出的图片保存为要求精度

    · 来源:http://emuch.net/bbs/viewthread.php?tid=2705843 杂志社对投稿图片的分辨率通常有如下要求: TIFF: Colour or greyscale ...

  9. (转)原始图像数据和PDF中的图像数据

    比较原始图像数据和PDF中的图像数据,结果见表1.1.表1.1中各种“解码器”的解释见本文后续的“PDF支持的图像格式”部分,“PDF中的图像数据”各栏中的数据来自开源的PdfView.如果您有兴趣查 ...

随机推荐

  1. 【设计模式】工厂方法(FactoryMethod)模式

    看不见PPT的请自行解决DNS污染问题. 相关类的代码: namespace FactoryPatternConsole.Model { public class Address { public s ...

  2. 【SharePoint】SharePoint2013中使用客户端对象模型给用户控件赋初值

    本文要实现的功能:新建一条列表记录,打开新建记录画面时,自动给[申请人]赋值为当前登录用户. 在SharePoint2010中,可以使用SPServices的SPFindPeoplePicker方法来 ...

  3. apache TIME_WAIT解决办法

    最近发现apache与负载均衡器的的连接数过多,而且大部分都是TIME_WAIT,调整apache2.conf后也没效果,最后百度到如下解决方案 通过调整内核参数解决 vi /etc/sysctl.c ...

  4. 谈 API 的撰写 - 子系统

    在做一个系统时,有一些子系统几乎是必备的:配置管理,CLI,以及测试框架. 配置管理 我们先说配置管理.一个系统的灵活度,和它的配置管理是离不开的.系统中存在的大量的预置的属性(下文简称 proper ...

  5. 公司的mysql-installer-community-5.7.19.0安装注意

    需要安装Microsoft Visual C++ 2013 Redistributable(x64) 和 Microsoft Visual C++ 2013 Redistributable(x86) ...

  6. UNP学习笔记(第十七章 ioctl操作)

    ioctl相当于一个杂物箱,它一直作为那些不适合归入其他精细定义类别的特性的系统接口. 本章笔记先放着,到时候有需要再看 ioctl函数 #include <unistd.h> int i ...

  7. Android开发第一讲之目录结构和程序的执行流程

    1.如何在eclipse当中,修改字体 下面的这种办法,可以更改xml的字体 窗口--首选项--常规--外观--颜色和字体--基本--文本字体--编辑Window --> Preferences ...

  8. 网络虚拟化基础协议之Geneve

    网络虚拟化最基础的技术莫过于分层(Overlay.Underlay),要实现分层有两种手段.一个是映射(Mapping),一个是封装(Encapsulation). 映射,主要思路是转发时替换报文语义 ...

  9. 怎么样自己动手写OS

    虽然我现在并不是从事内核方向,却本着探索计算机本质的想法学习的内核,自从写完这个内核以后真的发现对很多东西的理解都更深一层,所以专研内核,对我现在的工作是很有帮助的.我个人强烈建议师弟师妹们尽早地啃一 ...

  10. bugzilla 系列1安装

    安装好mysql yum install gcc perl* mod_perl-devel -y wget https://ftp.mozilla.org/pub/mozilla.org/webtoo ...