标题:求高手进来帮解决有关huffman图片压缩还原用C语言实现,已经列出部分主程序 ...
只看楼主
tomsa222
Rank: 1
等 级:新手上路
帖 子:1
专家分:0
注 册:2010-3-25
结帖率:0
已结贴  问题点数:20 回复次数:1 
求高手进来帮解决有关huffman图片压缩还原用C语言实现,已经列出部分主程序,请教高手帮忙完成整嗰可以运行的程序
效果如图所示

 
实现代码
(1)压缩主函数
int Huffman_Compression(char * infilename, char * outfilename)
{
       if ((ifile = fopen (infilename, "rb")) != NULL)
      {
        fseek (ifile, 0L, 2);
        file_size = (unsigned long) ftell (ifile);    //获得文件的大小
       fseek (ifile, 0L, 0);
        Get_frequency_count ();              //统计字符频率
        Build_initial_heap ();                //建立初始堆
        Build_code_tree ();                  //构造编码树
        if (!Generate_code_table ())           //产生编码表
        {
            printf ("ERROR! Cannot Compress.\n");
            return 0;
        }
        else
        {
            if ((ofile = fopen (outfilename, "wb")) != NULL)
            {//写文件头
                fwrite (&file_size, sizeof (file_size), 1, ofile);
                fwrite (code, 2, 256, ofile);
                fwrite (code_length, 1, 256, ofile);
                fseek (ifile, 0L, 0);
                Compress_image ();           //压缩数据
                fclose (ofile);
            }
            else
            {
                printf("\nERROR: Couldn't create output file %s\n", outfilename);
                return 0;
            }
}
        fclose (ifile);
    }
    else
    {
        printf ("\nERROR:  %s -- File not found!\n", infilename);
        return 0;
    }
    return 1;
}
(2)相关函数
//统计数据频率
/*通常在统计文件中字符频率时,耗费时间长,占用内存空间大。为降低时间复杂度和空间复杂度,这里直接用字符的十进制值作数组下标,在扫描过程中依次增加该字符出现的频率。*/
void Get_frequency_count ()
{
   register unsigned long  loop;
   for (loop = 0; loop < file_size; loop++)
      frequency_count[getc (ifile)]++;
}
//建立初始堆   
void Build_initial_heap ()
{
   void    reheap ();
   register unsigned short  loop;
   heap_length = 0;
   for (loop = 0; loop < 256; loop++)
      if (frequency_count[loop])
         heap[++heap_length] = (unsigned long) loop;
   for (loop = heap_length; loop > 0; loop--)
      reheap (loop);
}
//构造编码树
/*因为每个字节可表示的符号个数为256 个(对应于256 种颜色),所以二叉树有256 个叶结点,根据二叉树的性质总结点数为2•256- 1 = 511 个结点。这里用0~255 个元素来依次对应256 种颜色。由第256 以后的元素来依次对应形成的各个父结点的信息,即父结点的编号从256 开始。*/
     void Build_code_tree ()
{
   void    reheap ();
   register unsigned short  findex;
   register unsigned long   heap_value;
   while (heap_length != 1)
   {
      heap_value = heap[1];
      heap[1]    = heap[heap_length--];
      reheap (1);
      findex = heap_length + 255;
      frequency_count[findex] = frequency_count[heap[1]] +
                                frequency_count[heap_value];
      father[heap_value] =  findex;
      father[heap[1]]    = -findex;
      heap[1]          =  findex;
      reheap (1);
   }
   father[256] = 0;
}
//生成编码表
unsigned short  Generate_code_table ()
{
   register unsigned short  loop;
   register unsigned short  current_length;
   register unsigned short  current_bit;
   unsigned short  bitcode;
   short           parent;
   for (loop = 0; loop < 256; loop++)
      if (frequency_count[loop])
      {
         current_length = bitcode = 0;
         current_bit = 1;
         parent = father[loop];
         while (parent)
         {
            if (parent < 0)
            {
               bitcode += current_bit;
               parent = -parent;
            }
            parent = father[parent];
            current_bit <<= 1;
            current_length++;
         }
         code[loop] = bitcode;
         if (current_length > 16)  return (0);
         else
            code_length[loop] = (unsigned char) current_length;
      }
      else  code[loop] = code_length[loop] = 0;
   return (1);
}
//压缩数据
void Compress_image ()
{
   register unsigned int    thebyte = 0;
   register short           loop1;
   register unsigned short  current_code;
   register unsigned long   loop;
   unsigned short  current_length, dvalue;
   unsigned long   curbyte = 0;
   short           curbit = 7;
   for (loop = 0L; loop < file_size; loop++)
   {
      dvalue        = (unsigned short) getc (ifile);
      current_code   = code[dvalue];
      current_length  = (unsigned short) code_length[dvalue];
      for (loop1 = current_length-1; loop1 >= 0; --loop1)
      {
         if ((current_code >> loop1) & 1)
            thebyte |= (char) (1 << curbit);
         if (--curbit < 0)
         {
            putc (thebyte, ofile);
            thebyte = 0;
            curbyte++;
            curbit = 7;
         }
      }
   }
   putc (thebyte, ofile);
   compress_charcount = ++curbyte;
}

 
 
 
实现代码
(1)解压主函数
int  Huffman_Decompression(char * infilename, char * outfilename)
{
    if ((ifile = fopen (infilename, "rb")) != NULL)
    {   //读取文件头
        fread (&file_size, sizeof (file_size), 1, ifile);
        fread (code, 2, 256, ifile);
        fread (code_length, 1, 256, ifile);
        Build_decomp_tree ();             //创建解压缩树
        if ((ofile = fopen (outfilename, "wb")) != NULL){
            Decompress_image();          //解压缩数据
            fclose (ofile);}
        else    {
            printf ("\nERROR:  Couldn't create output file %s\n", outfilename);
            return 0;    }
        fclose (ifile);
    }
    else
    {
        printf ("\nERROR:  %s -- File not found!\n", infilename);
        return 0;
    }
    return 1;
}
(2)相关函数
void  Build_decomp_tree ()     //创建解压缩树
{
   register unsigned short  loop1, current_index;
   unsigned short  loop, current_node = 1;
   decomp_tree[1] = 1;
   for (loop = 0; loop < 256; loop++)
   {
      if (code_length[loop])
      {
          current_index = 1;
          for (loop1 = code_length[loop] - 1; loop1 > 0; loop1--)
          {
             current_index = (decomp_tree[current_index] << 1) +
                             ((code[loop] >> loop1) & 1);
             if (!(decomp_tree[current_index]))
       decomp_tree[current_index] = ++current_node;
          }
decomp_tree[(decomp_tree[current_index] << 1) +                                                (code[loop] & 1)] = -loop;
    }
   }
}
void  Decompress_image ()        //进行解压缩操作
{
   register unsigned short  cindex = 1;
   register char            curchar;
   register short           bitshift;
   unsigned long  charcount = 0L;
   while (charcount < file_size)
 {
      curchar = (char) getc (ifile);
      for (bitshift = 7; bitshift >= 0; --bitshift)
      {
          cindex = (cindex << 1) + ((curchar >> bitshift) & 1);
          if (decomp_tree[cindex] <= 0) {
            putc ((int) (-decomp_tree[cindex]), ofile);
            if ((++charcount) == file_size)    bitshift = 0;
           else     cindex = 1; }
         else  cindex = decomp_tree[cindex];
      }
   }
}
搜索更多相关主题的帖子: 压缩 huffman 主程序 C语言 
2010-03-26 18:22
hzh512
Rank: 9Rank: 9Rank: 9
等 级:蜘蛛侠
威 望:6
帖 子:234
专家分:1333
注 册:2009-6-5
得分:20 
哈夫曼(Huffman)编码是Huffman于1952年为压缩文本文件建立的,压缩图像不高效,因为它要扫描文件2遍,劝LZ换一种方法吧,用LZW算法吧。LZW把每一个第一次出现的字符串用一个数值来编码,在还原程序中再将这个数值还成原来的字符串。例如:用数值0x100代替字符串“abccddeee”,每当出现该字符串时,都用0x100代替,这样就起到了压缩的作用。至于0x100与字符串的对应关系则是在压缩过程中动态生成的,而且这种对应关系隐含在压缩数据中,随着解压缩的进行这张编码表会从压缩数据中逐步得到恢复,后面的压缩数据再根据前面数据产生的对应关系产生更多的对应关系,直到压缩文件结束为止。

编程=用几种语言在某个或几个平台上通过抽象思维运用一系列算法来解决现实中问题的手段
2010-03-26 19:27



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-300626-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.059603 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved