霍夫曼编码的分析与实现(6)

/*将字符对应的编码写入压缩数据的缓存中*/
        for(i=0; i<table[c].size; i++)
        {
            if(opos % 8 == 0)
            {
                /*为压缩数据的缓存区分配另一个字节*/
                if((temp = (unsigned char *)realloc(comp,(opos/8)+1)) == NULL)
                {
                    free(comp);
                    return -1;
                }
                comp = temp;
            }
            cpos = (sizeof(short)*8) - table[c].size + i;
            bit_set(comp, opos, bit_get((unsigned char *)&table[c].code,cpos));
            opos++;
        }
        ipos++;
    }
    /*指向压缩数据的缓冲区*/
    *compressed = comp;

/*返回压缩缓冲区中的字节数*/
    return ((opos - 1) / 8) + 1;
}

/*huffman_uncompress  解压缩霍夫曼数据*/
int huffman_uncompress(const unsigned char *compressed, unsigned char **original)
{
    BiTree      *tree;
    BiTreeNode  *node;
    int          freqs[UCHAR_MAX + 1],
                hsize,
                size,
                ipos,opos,
                state,
                c;
    unsigned char *orig,*temp;
   
    /*初始化*/
    *original = orig = NULL;
   
    /*从压缩数据缓冲区中获取头文件信息*/
    hize = sizeof(int) + (UCHAR_MAX + 1);
    memcpy(&size,compressed,sizeof(int));
   
    for(c=0; c<=UCHAR_MAX; c++)
        freqs[c] = compressed[sizeof(int) + c];
   
    /*重建前面压缩数据时的霍夫曼树*/
    if(bulid_tree(freqs,&tree) != 0)
        return -1;
   
    /*解压缩数据*/
    ipos = hsize * 8;
    opos = 0;
    node = bitree_root(tree);
   
    while(opos < size)
    {
        /*从压缩数据中获取位状态*/
        state = bit_get(compressed,ipos);
        ipos++;
       
        if(state == 0)
        {
            /*向左移动*/
            if(bitree_is_eob(node) || bitree_is_eob(bitree_left(node)))
            {
                bitree_destroy(tree);
                free(tree);
                return -1;
            }
            else node = bitree_left(node);
        }
        else
        {
            /*向右移动*/
            if(bitree_is_eob(node) || bitree_is_eob(bitree_right(node)))
            {
                bitree_destroy(tree);
                free(tree);
                return -1;
            }
            else node = bitree_right(node);
        }
       
        if(bitree_is_eob(bitree_left(node)) && bitree_is_eob(bitree_right(node)))
        {
            /*将叶子结点中的符号写入原始数据缓冲区*/
            if(opos > 0)
            {
                if((temp = (unsigned char *)realloc(orig,opos+1)) == NULL)
                {
                    bitree_destroy(tree);
                    free(tree);
                    free(orig);
                    return -1;
                }
                orig = temp;
            }
            else
            {
                if((orig = (unsigned char *)malloc(1)) == NULL)
                {
                    bitree_destroy(tree);
                    free(tree);
                    return -1;
                }
            }
           
            orig[opos] = ((HuffNode *)bitree_data(node))->symbol;
            opos++;
           
            /*返回到霍夫曼树的顶部*/
            node = bitree_root(tree);
        }
    }
    bitree_destroy(tree);
    free(tree);
   
    /*把向原始数据缓冲区*/
    *original = orig;
   
    /*返回原始数据中的字节数*/
    return opos;
}

Linux公社的RSS地址:https://www.linuxidc.com/rssFeed.aspx

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/c722a48700460ca4f480e76d94e5b876.html