/*************************************************************************** * Function : BitArrayShiftLeft * Description: This function shifts the bits in a bit array to the left * by the amount of positions specified. * Parameters : ba - pointer to the bit array 0 is the msb of the first * unsigned char in the bit array. * shifts - number of bits to shift by. * Effects : The bit array data pointed to by ba is shifted to the left. * New bits shifted in will be set to 0. * Returned : None ***************************************************************************/ void BitArrayShiftLeft(bit_array_t *ba, unsigned int shifts) { int i, j; int chars = shifts / CHAR_BIT; /* number of whole byte shifts */ shifts = shifts % CHAR_BIT; /* number of bit shifts remaining */ if (ba == NULL) { return; /* nothing to shift */ } if (shifts >= ba->numBits) { /* all bits have been shifted off */ BitArrayClearAll(ba); return; } /* first handle big jumps of bytes */ if (chars > 0) { for (i = 0; (i + chars) < BITS_TO_CHARS(ba->numBits); i++) { ba->array[i] = ba->array[i + chars]; } /* now zero out new bytes on the right */ for (i = BITS_TO_CHARS(ba->numBits); chars > 0; chars--) { ba->array[i - chars] = 0; } } /* now we have at most CHAR_BIT - 1 bit shifts across the whole array */ for (i = 0; i < shifts; i++) { for (j = 0; j < BIT_CHAR(ba->numBits - 1); j++) { ba->array[j] <<= 1; /* handle shifts across byte bounds */ if (ba->array[j + 1] & MS_BIT) { ba->array[j] |= 0x01; } } ba->array[BIT_CHAR(ba->numBits - 1)] <<= 1; } }
/**************************************************************************** * 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; }
/**************************************************************************** * 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; }
/*************************************************************************** * Function : BitArrayShiftRight * Description: This function shifts the bits in a bit array to the right * by the amount of positions specified. * Parameters : ba - pointer to the bit array 0 is the msb of the first * unsigned char in the bit array. * shifts - number of bits to shift by. * Effects : The bit array data pointed to by ba is shifted to the * right. New bits shifted in will be set to 0. * Returned : None ***************************************************************************/ void BitArrayShiftRight(bit_array_t *ba, unsigned int shifts) { int i, j; unsigned char mask; int chars = shifts / CHAR_BIT; /* number of whole byte shifts */ shifts = shifts % CHAR_BIT; /* number of bit shifts remaining */ if (ba == NULL) { return; /* nothing to shift */ } if (shifts >= ba->numBits) { /* all bits have been shifted off */ BitArrayClearAll(ba); return; } /* first handle big jumps of bytes */ if (chars > 0) { for (i = BIT_CHAR(ba->numBits - 1); (i - chars) >= 0; i--) { ba->array[i] = ba->array[i - chars]; } /* now zero out new bytes on the right */ for (; chars > 0; chars--) { ba->array[chars - 1] = 0; } } /* now we have at most CHAR_BIT - 1 bit shifts across the whole array */ for (i = 0; i < shifts; i++) { for (j = BIT_CHAR(ba->numBits - 1); j > 0; j--) { ba->array[j] >>= 1; /* handle shifts across byte bounds */ if (ba->array[j - 1] & 0x01) { ba->array[j] |= MS_BIT; } } ba->array[0] >>= 1; } /*********************************************************************** * zero any spare bits that are beyond the end of the bit array so * increment and decrement are consistent. ***********************************************************************/ i = ba->numBits % CHAR_BIT; if (i != 0) { mask = UCHAR_MAX << (CHAR_BIT - i); ba->array[BIT_CHAR(ba->numBits - 1)] &= mask; } }
int CHuffmanDecode(struct CHuffman *ch) { bit_file_t bfpIn; int i, newBit; bfpIn.mode = BF_READ; bfpIn.buf = ch->inBuf; bfpIn.bufLen = ch->inLen; BitFileInit(&bfpIn); /* open binary output file and bitfile input file */ /* decode input file */ ch->outIndex = 0; if (!ch->resume) { BitArrayClearAll(ch->code); ch->decode_length = 0; } while (1) { newBit = BitFileGetBit(&bfpIn); if (newBit == EOF) { fprintf(stderr, "error reading bitfile\n"); exit(1); } if (newBit == BUFFER_EMPTY) { ch->resume = 1; return BUFFER_EMPTY; } if (newBit != 0) { BitArraySetBit(ch->code, ch->decode_length); } ch->decode_length++; if (ch->lenIndex[ch->decode_length] != NUM_CHARS) { /* there are code of this length */ for(i = ch->lenIndex[ch->decode_length]; (i < NUM_CHARS) && (ch->canonicalList[i].codeLen == ch->decode_length); i++) { if (BitArrayCompare(ch->canonicalList[i].code, ch->code) == 0) { /* we just read a symbol output decoded value */ if (ch->canonicalList[i].value == EOF_CHAR) { if (BitFileByteAlign(&bfpIn)) { fprintf(stderr, "buffer full\n"); exit(1); } } else { if (ch->outIndex >= ch->outLen) { /* buffer limit reached */ fprintf(stderr, "buffer full\n"); exit(1); } ch->outBuf[ch->outIndex++] = ch->canonicalList[i].value; } BitArrayClearAll(ch->code); ch->decode_length = 0; break; } } } } ch->resume = 0; /* close all files */ BitFileClose(&bfpIn); return 0; }