예제 #1
0
파일: huflocal.c 프로젝트: ecolitan/fatics
/****************************************************************************
*   Function   : GenerateTreeFromFile
*   Description: This routine creates a huffman tree optimized for encoding
*                the file passed as a parameter.
*   Parameters : inFile - Name of file to create tree for
*   Effects    : Huffman tree is built for file.
*   Returned   : Pointer to resulting tree.  NULL on failure.
****************************************************************************/
huffman_node_t *GenerateTreeFromFile(FILE *inFile)
{
    huffman_node_t *huffmanTree;              /* root of huffman tree */
    int c;

    /* allocate array of leaves for all possible characters */
    for (c = 0; c < NUM_CHARS; c++)
    {
        if ((huffmanArray[c] = AllocHuffmanNode(c)) == NULL)
        {
            /* allocation failed clear existing allocations */
            for (c--; c >= 0; c--)
            {
                free(huffmanArray[c]);
            }
            return NULL;
        }
    }

    /* count occurrence of each character */
    while ((c = fgetc(inFile)) != EOF)
    {
        if (huffmanArray[c]->count < COUNT_T_MAX)
        {
            /* increment count for character and include in tree */
            huffmanArray[c]->count++;
            huffmanArray[c]->ignore = FALSE;
        }
        else
        {
            fprintf(stderr,
                "Input file contains too many 0x%02X to count.\n", c);
            return NULL;
        }
    }
    
    /* estimate the freqency of the end of a string -- Wil Mahan */
    huffmanArray[EOF_CHAR]->count = 1;
    huffmanArray[EOF_CHAR]->ignore = FALSE;

    /* put array of leaves into a huffman tree */
    huffmanTree = BuildHuffmanTree(huffmanArray, NUM_CHARS);

    return huffmanTree;
}
예제 #2
0
/****************************************************************************
*   Function   : GenerateTreeFromFile
*   Description: This routine creates a huffman tree optimized for encoding
*                the file passed as a parameter.
*   Parameters : inFile - Name of file to create tree for
*   Effects    : Huffman tree is built for file.
*   Returned   : Pointer to resulting tree
****************************************************************************/
huffman_node_t *GenerateTreeFromFile(char *inFile)
{
    huffman_node_t *huffmanTree;              /* root of huffman tree */
    int c;
    FILE *fp;

    /* open file as binary */
    if ((fp = fopen(inFile, "rb")) == NULL)
    {
        perror(inFile);
        exit(EXIT_FAILURE);
    }

    /* allocate array of leaves for all possible characters */
    for (c = 0; c < NUM_CHARS; c++)
    {
        huffmanArray[c] = AllocHuffmanNode(c);
    }

    /* count occurrence of each character */
    while ((c = fgetc(fp)) != EOF)
    {
        if (totalCount < COUNT_T_MAX)
        {
            totalCount++;

            /* increment count for character and include in tree */
            huffmanArray[c]->count++;       /* check for overflow */
            huffmanArray[c]->ignore = FALSE;
        }
        else
        {
            fprintf(stderr,
                "Number of characters in file is too large to count.\n");
            exit(EXIT_FAILURE);
        }
    }

    fclose(fp);

    /* put array of leaves into a huffman tree */
    huffmanTree = BuildHuffmanTree(huffmanArray, NUM_CHARS);

    return(huffmanTree);
}
예제 #3
0
/****************************************************************************
*   Function   : DecodeFile
*   Description: This function decodes a huffman encode file, writing the
*                results to the specified output file.
*   Parameters : ht - pointer to array of tree node pointers
*                inFile - file to decode
*                outFile - where to output results (NULL -> stdout)
*   Effects    : inFile is decode and the results are written to outFile.
*   Returned   : None
****************************************************************************/
void DecodeFile(huffman_node_t **ht, char *inFile, char *outFile)
{
    huffman_node_t *huffmanTree, *currentNode;
    int i, c;
    FILE *fpIn, *fpOut;

    if ((fpIn = fopen(inFile, "rb")) == NULL)
    {
        perror(inFile);
        exit(EXIT_FAILURE);
        return;
    }

    if (outFile == NULL)
    {
        fpOut = stdout;
    }
    else
    {
        if ((fpOut = fopen(outFile, "wb")) == NULL)
        {
            perror(outFile);
            exit(EXIT_FAILURE);
        }
    }

    /* allocate array of leaves for all possible characters */
    for (i = 0; i < NUM_CHARS; i++)
    {
        ht[i] = AllocHuffmanNode(i);
    }

    /* populate leaves with frequency information from file header */
    ReadHeader(ht, fpIn);

    /* put array of leaves into a huffman tree */
    huffmanTree = BuildHuffmanTree(ht, NUM_CHARS);

    /* now we should have a tree that matches the tree used on the encode */
    currentNode = huffmanTree;

    /* handle one symbol codes */
    if (currentNode->value != COMPOSITE_NODE)
    {
        while ((c = fgetc(fpIn)) != EOF);    /* read to force EOF below */

        /* now just write out number of required symbols */
        while(totalCount)
        {
            fputc(currentNode->value, fpOut);
            totalCount--;
        }
    }

    while ((c = fgetc(fpIn)) != EOF)
    {
        /* traverse the tree finding matches for our characters */
        for(i = 0; i < 8; i++)
        {
            if (c & 0x80)
            {
                currentNode = currentNode->right;
            }
            else
            {
                currentNode = currentNode->left;
            }

            if (currentNode->value != COMPOSITE_NODE)
            {
                /* we've found a character */
                fputc(currentNode->value, fpOut);
                currentNode = huffmanTree;
                totalCount--;

                if (totalCount == 0)
                {
                    /* we've just written the last character */
                    break;
                }
            }

            c <<= 1;
        }
    }

    /* close all files */
    fclose(fpIn);
    fclose(fpOut);
    FreeHuffmanTree(huffmanTree);     /* free allocated memory */
}
예제 #4
0
/****************************************************************************
*   Function   : HuffmanDecodeFile
*   Description: This routine reads a Huffman coded file and writes out a
*                decoded version of that file.
*   Parameters : inFile - Open file pointer for file to decode
*                outFile - Open file pointer for file receiving decoded data
*   Effects    : Huffman encoded file is decoded
*   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 HuffmanDecodeFile(FILE *inFile, FILE *outFile)
{
    huffman_node_t *huffmanArray[NUM_CHARS];    /* array of all leaves */
    huffman_node_t *huffmanTree;
    huffman_node_t *currentNode;
    int i, c;
    bit_file_t *bInFile;

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

    bInFile = MakeBitFile(inFile, BF_READ);

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

    /* allocate array of leaves for all possible characters */
    for (i = 0; i < NUM_CHARS; i++)
    {
        if ((huffmanArray[i] = AllocHuffmanNode(i)) == NULL)
        {
            /* allocation failed clear existing allocations */
            for (i--; i >= 0; i--)
            {
                free(huffmanArray[i]);
            }

            inFile = BitFileToFILE(bInFile);
            return -1;
        }
    }

    /* populate leaves with frequency information from file header */
    if (0 != ReadHeader(huffmanArray, bInFile))
    {
        for (i = 0; i < NUM_CHARS; i++)
        {
            free(huffmanArray[i]);
        }

        inFile = BitFileToFILE(bInFile);
        return -1;
    }

    /* put array of leaves into a huffman tree */
    if ((huffmanTree = BuildHuffmanTree(huffmanArray, NUM_CHARS)) == NULL)
    {
        FreeHuffmanTree(huffmanTree);
        inFile = BitFileToFILE(bInFile);
        return -1;
    }

    /* now we should have a tree that matches the tree used on the encode */
    currentNode = huffmanTree;

    while ((c = BitFileGetBit(bInFile)) != EOF)
    {
        /* traverse the tree finding matches for our characters */
        if (c != 0)
        {
            currentNode = currentNode->right;
        }
        else
        {
            currentNode = currentNode->left;
        }

        if (currentNode->value != COMPOSITE_NODE)
        {
            /* we've found a character */
            if (currentNode->value == EOF_CHAR)
            {
                /* we've just read the EOF */
                break;
            }

            fputc(currentNode->value, outFile); /* write out character */
            currentNode = huffmanTree;          /* back to top of tree */
        }
    }

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

    return 0;
}