Example #1
0
/****************************************************************************
*   Function   : AssignCanonicalCode
*   Description: This function accepts a list of symbols sorted by their
*                code lengths, and assigns a canonical Huffman code to each
*                symbol.
*   Parameters : cl - sorted list of symbols to have code values assigned
*   Effects    : cl stores a list of canonical codes sorted by the length
*                of the code used to encode the symbol.
*   Returned   : TRUE for success, FALSE for failure
****************************************************************************/
static int AssignCanonicalCodes(canonical_list_t *cl)
{
    int i;
    byte_t length;
    bit_array_t *code;

    /* assign the new codes */
    code = BitArrayCreate(256);
    BitArrayClearAll(code);

    length = cl[(NUM_CHARS - 1)].codeLen;

    for(i = (NUM_CHARS - 1); i >= 0; i--)
    {
        /* bail if we hit a zero len code */
        if (cl[i].codeLen == 0)
        {
            break;
        }

        /* adjust code if this length is shorter than the previous */
        if (cl[i].codeLen < length)
        {
            BitArrayShiftRight(code, (length - cl[i].codeLen));
            length = cl[i].codeLen;
        }

        /* assign left justified code */
        if ((cl[i].code = BitArrayDuplicate(code)) == NULL)
        {
            perror("Duplicating code");
            BitArrayDestroy(code);
            return FALSE;
        }

        BitArrayShiftLeft(cl[i].code, 256 - length);

        BitArrayIncrement(code);
    }

    BitArrayDestroy(code);
    return TRUE;
}
Example #2
0
/****************************************************************************
*   Function   : MakeCodeList
*   Description: This function uses a huffman tree to build a list of codes
*                and their length for each encoded symbol.  This simplifies
*                the encoding process.  Instead of traversing a tree in
*                search of the code for any symbol, the code maybe found
*                by accessing codeList[symbol].code.
*   Parameters : ht - pointer to root of huffman tree
*                codeList - code list to populate.
*   Effects    : Code values are filled in for symbols in a code list.
*   Returned   : 0 for success, -1 for failure.  errno will be set in the
*                event of a failure.
****************************************************************************/
static int MakeCodeList(huffman_node_t *ht, code_list_t *codeList)
{
    bit_array_t *code;
    byte_t depth = 0;

    if((code = BitArrayCreate(EOF_CHAR)) == NULL)
    {
        perror("Unable to allocate bit array");
        return -1;
    }

    BitArrayClearAll(code);

    for(;;)
    {
        /* follow this branch all the way left */
        while (ht->left != NULL)
        {
            BitArrayShiftLeft(code, 1);
            ht = ht->left;
            depth++;
        }

        if (ht->value != COMPOSITE_NODE)
        {
            /* enter results in list */
            codeList[ht->value].codeLen = depth;
            codeList[ht->value].code = BitArrayDuplicate(code);
            if (codeList[ht->value].code == NULL)
            {
                perror("Unable to allocate bit array");
                BitArrayDestroy(code);
                return -1;
            }

            /* now left justify code */
            BitArrayShiftLeft(codeList[ht->value].code, EOF_CHAR - depth);
        }

        while (ht->parent != NULL)
        {
            if (ht != ht->parent->right)
            {
                /* try the parent's right */
                BitArraySetBit(code, (EOF_CHAR - 1));
                ht = ht->parent->right;
                break;
            }
            else
            {
                /* parent's right tried, go up one level yet */
                depth--;
                BitArrayShiftRight(code, 1);
                ht = ht->parent;
            }
        }

        if (ht->parent == NULL)
        {
            /* we're at the top with nowhere to go */
            break;
        }
    }

    BitArrayDestroy(code);
    return 0;
}
Example #3
0
/****************************************************************************
*   Function   : HuffmanEncodeFile
*   Description: This routine genrates a huffman tree optimized for a file
*                and writes out an encoded version of that file.
*   Parameters : inFile - Open file pointer for file to encode (must be
*                         rewindable).
*                outFile - Open file pointer for file receiving encoded data
*   Effects    : File is Huffman encoded
*   Returned   : 0 for success, -1 for failure.  errno will be set in the
*                event of a failure.  Either way, inFile and outFile will
*                be left open.
****************************************************************************/
int HuffmanEncodeFile(FILE *inFile, FILE *outFile)
{
    huffman_node_t *huffmanTree;        /* root of huffman tree */
    code_list_t codeList[NUM_CHARS];    /* table for quick encode */
    bit_file_t *bOutFile;
    int c;

    /* validate input and output files */
    if ((NULL == inFile) || (NULL == outFile))
    {
        errno = ENOENT;
        return -1;
    }

    bOutFile = MakeBitFile(outFile, BF_WRITE);

    if (NULL == bOutFile)
    {
        perror("Making Output File a BitFile");
        return -1;
    }

    /* build tree */
    if ((huffmanTree = GenerateTreeFromFile(inFile)) == NULL)
    {
        outFile = BitFileToFILE(bOutFile);
        return -1;
    }

    /* build a list of codes for each symbol */

    /* initialize code list */
    for (c = 0; c < NUM_CHARS; c++)
    {
        codeList[c].code = NULL;
        codeList[c].codeLen = 0;
    }

    if (0 != MakeCodeList(huffmanTree, codeList))
    {
        outFile = BitFileToFILE(bOutFile);
        return -1;
    }

    /* write out encoded file */

    /* write header for rebuilding of tree */
    WriteHeader(huffmanTree, bOutFile);

    /* read characters from file and write them to encoded file */
    rewind(inFile);         /* start another pass on the input file */

    while((c = fgetc(inFile)) != EOF)
    {
        BitFilePutBits(bOutFile,
                       BitArrayGetBits(codeList[c].code),
                       codeList[c].codeLen);
    }

    /* now write EOF */
    BitFilePutBits(bOutFile,
                   BitArrayGetBits(codeList[EOF_CHAR].code),
                   codeList[EOF_CHAR].codeLen);

    /* free the code list */
    for (c = 0; c < NUM_CHARS; c++)
    {
        if (codeList[c].code != NULL)
        {
            BitArrayDestroy(codeList[c].code);
        }
    }

    /* clean up */
    outFile = BitFileToFILE(bOutFile);          /* make file normal again */
    FreeHuffmanTree(huffmanTree);               /* free allocated memory */

    return 0;
}
Example #4
0
int CHuffmanInit(struct CHuffman *ch)
{
    int i;
    /* initialize canonical list */
    for (i = 0; i < NUM_CHARS; i++) {
        ch->canonicalList[i].codeLen = 0;
        ch->canonicalList[i].code = NULL;
    }
    
    if (!ReadHeader(ch->canonicalList)) {
        return FALSE;
    }

    /* sort the header by code length */
    qsort(ch->canonicalList, NUM_CHARS, sizeof(canonical_list_t),
        CompareByCodeLen);
    
    if (AssignCanonicalCodes(ch->canonicalList) == 0)
    {
        /* failed to assign codes */
        for (i = 0; i < NUM_CHARS; i++)
        {
            if(ch->canonicalList[i].code != NULL)
            {
                BitArrayDestroy(ch->canonicalList[i].code);
            }
        }

        return FALSE;
    }

    if (ch->for_encode) {
	    /* re-sort list in lexical order for use by encode algorithm */
	    qsort(ch->canonicalList, NUM_CHARS, sizeof(canonical_list_t),
		CompareBySymbolValue);
    }
    else {
		/* decoding */
		    /* allocate canonical code list */
		    ch->code = BitArrayCreate(256);
		    if (ch->code == NULL) {
			perror("Bit array allocation");
			return FALSE;
		    }
       		ch->resume = 0;

	    /* create an index of first code at each possible length */
	    for (i = 0; i < NUM_CHARS; i++)
	    {
		ch->lenIndex[i] = NUM_CHARS;
	    }

	    for (i = 0; i < NUM_CHARS; i++)
	    {
		if (ch->lenIndex[ch->canonicalList[i].codeLen] > i)
		{
		    /* first occurance of this code length */
		    ch->lenIndex[ch->canonicalList[i].codeLen] = i;
		}
	    }
    }

    return TRUE;
}