/**************************************************************************** * 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; }
/**************************************************************************** * 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); }
/**************************************************************************** * 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 */ }
/**************************************************************************** * 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; }