/**************************************************************************** * Function : EncodeFile * Description: This function uses the provide Huffman tree to encode * the file passed as a parameter. * Parameters : ht - pointer to root of tree * inFile - file to encode * outFile - where to output results (NULL -> stdout) * Effects : inFile is encoded and the code plus the results are * written to outFile. * Returned : None ****************************************************************************/ void EncodeFile(huffman_node_t *ht, char *inFile, char *outFile) { code_list_t codeList[NUM_CHARS]; /* table for quick encode */ FILE *fpIn, *fpOut; int c, i, bitCount; char bitBuffer; /* open binary input and output files */ if ((fpIn = fopen(inFile, "rb")) == NULL) { perror(inFile); exit(EXIT_FAILURE); } if (outFile == NULL) { fpOut = stdout; } else { if ((fpOut = fopen(outFile, "wb")) == NULL) { perror(outFile); FreeHuffmanTree(ht); exit(EXIT_FAILURE); } } WriteHeader(ht, fpOut); /* write header for rebuilding of tree */ MakeCodeList(ht, codeList); /* convert code to easy to use list */ /* write encoded file 1 byte at a time */ bitBuffer = 0; bitCount = 0; while((c = fgetc(fpIn)) != EOF) { /* shift in bits */ for(i = 0; i < codeList[c].codeLen; i++) { bitCount++; bitBuffer = (bitBuffer << 1) | (TestBit256(codeList[c].code, i) == 1); if (bitCount == 8) { /* we have a byte in the buffer */ fputc(bitBuffer, fpOut); bitCount = 0; } } } /* now handle spare bits */ if (bitCount != 0) { bitBuffer <<= 8 - bitCount; fputc(bitBuffer, fpOut); } fclose(fpIn); fclose(fpOut); }
/**************************************************************************** * 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; }