/*****************************************************************************/ /* *-------------------------------------------------------------- * * EmitDht -- * * Emit a DHT marker, follwed by the huffman data. * * Results: * None * * Side effects: * None * *-------------------------------------------------------------- */ public void EmitDht(int index) { int i; HuffmanTable htbl = huffTable[index]; EmitMarker(JpegMarker.M_DHT); int length = 0; for (i = 1; i <= 16; i++) { length += htbl.bits[i]; } Emit2bytes(length + 2 + 1 + 16); EmitByte((uint8)index); for (i = 1; i <= 16; i++) { EmitByte(htbl.bits[i]); } for (i = 0; i < length; i++) { EmitByte(htbl.huffval[i]); } }
public void EncodeOneDiff(int diff, ref HuffmanTable dctbl) { // Encode the DC coefficient difference per section F.1.2.1 int temp = diff; int temp2 = diff; if (temp < 0) { temp = -temp; // For a negative input, want temp2 = bitwise complement of // abs (input). This code assumes we are on a two's complement // machine. temp2--; } // Find the number of bits needed for the magnitude of the coefficient int nbits = temp >= 256 ? numBitsTable[temp >> 8] + 8 : numBitsTable[temp & 0xFF]; // Emit the Huffman-coded symbol for the number of bits EmitBits(dctbl.ehufco[nbits], dctbl.ehufsi[nbits]); // Emit that number of bits of the value, if positive, // or the complement of its magnitude, if negative. // If the number of bits is 16, there is only one possible difference // value (-32786), so the lossless JPEG spec says not to output anything // in that case. So we only need to output the diference value if // the number of bits is between 1 and 15. if ((nbits & 15) != 0) { EmitBits(temp2 & (0x0FFFF >> (16 - nbits)), nbits); } }
/*****************************************************************************/ /* *-------------------------------------------------------------- * * GenHuffCoding -- * * Generate the optimal coding for the given counts. * This algorithm is explained in section K.2 of the * JPEG standard. * * Results: * htbl->bits and htbl->huffval are constructed. * * Side effects: * None. * *-------------------------------------------------------------- */ private void GenHuffCoding(ref HuffmanTable htbl, uint32[] freq) { int i; int j; const int MAX_CLEN = 32; // assumed maximum initial code length uint8[] bits = new uint8[MAX_CLEN + 1]; // bits [k] = # of symbols with code length k short[] codesize = new short[257]; // codesize [k] = code length of symbol k short[] others = new short[257]; // next symbol in current branch of tree //memset(bits, 0, sizeof(bits)); //memset(codesize, 0, sizeof(codesize)); for (i = 0; i < 257; i++) { others[i] = -1; // init links to empty } // Including the pseudo-symbol 256 in the Huffman procedure guarantees // that no real symbol is given code-value of all ones, because 256 // will be placed in the largest codeword category. freq[256] = 1; // make sure there is a nonzero count // Huffman's basic algorithm to assign optimal code lengths to symbols while (true) { // Find the smallest nonzero frequency, set c1 = its symbol. // In case of ties, take the larger symbol number. int c1 = -1; uint32 v = 0xFFFFFFFF; for (i = 0; i <= 256; i++) { if ((freq[i]) != 0 && freq[i] <= v) { v = freq[i]; c1 = i; } } // Find the next smallest nonzero frequency, set c2 = its symbol. // In case of ties, take the larger symbol number. int c2 = -1; v = 0xFFFFFFFF; for (i = 0; i <= 256; i++) { if ((freq[i]) != 0 && freq[i] <= v && i != c1) { v = freq[i]; c2 = i; } } // Done if we've merged everything into one frequency. if (c2 < 0) { break; } // Else merge the two counts/trees. freq[c1] += freq[c2]; freq[c2] = 0; // Increment the codesize of everything in c1's tree branch. codesize[c1]++; while (others[c1] >= 0) { c1 = others[c1]; codesize[c1]++; } // chain c2 onto c1's tree branch others[c1] = (short)c2; // Increment the codesize of everything in c2's tree branch. codesize[c2]++; while (others[c2] >= 0) { c2 = others[c2]; codesize[c2]++; } } // Now count the number of symbols of each code length. for (i = 0; i <= 256; i++) { if (codesize[i] != 0) { // The JPEG standard seems to think that this can't happen, // but I'm paranoid... if (codesize[i] > MAX_CLEN) { throw new Exception("Huffman code size table overflow"); } bits[codesize[i]]++; } } // JPEG doesn't allow symbols with code lengths over 16 bits, so if the pure // Huffman procedure assigned any such lengths, we must adjust the coding. // Here is what the JPEG spec says about how this next bit works: // Since symbols are paired for the longest Huffman code, the symbols are // removed from this length category two at a time. The prefix for the pair // (which is one bit shorter) is allocated to one of the pair; then, // skipping the BITS entry for that prefix length, a code word from the next // shortest nonzero BITS entry is converted into a prefix for two code words // one bit longer. for (i = MAX_CLEN; i > 16; i--) { while (bits[i] > 0) { // Kludge: I have never been able to test this logic, and there // are comments on the web that this encoder has bugs with 16-bit // data, so just throw an error if we get here and revert to a // default table. - tknoll 12/1/03. //DNG_REPORT("Info: Optimal huffman table bigger than 16 bits"); //ThrowProgramError(); throw new Exception("Info: Optimal huffman table bigger than 16 bits"); // Original logic: j = i - 2; // find length of new prefix to be used while (bits[j] == 0) { j--; } bits[i] -= 2; // remove two symbols bits[i - 1]++; // one goes in this length bits[j + 1] += 2; // two new symbols in this length bits[j]--; // symbol of this length is now a prefix } } // Remove the count for the pseudo-symbol 256 from // the largest codelength. while (bits[i] == 0) // find largest codelength still in use { i--; } bits[i]--; // Return final symbol counts (only for lengths 0..16). //memcpy(htbl->bits, bits, sizeof(htbl->bits)); Array.Copy(bits, htbl.bits, htbl.bits.Length); // Return a list of the symbols sorted by code length. // It's not real clear to me why we don't need to consider the codelength // changes made above, but the JPEG spec seems to think this works. int p = 0; for (i = 1; i <= MAX_CLEN; i++) { for (j = 0; j <= 255; j++) { if (codesize[j] == i) { htbl.huffval[p] = (uint8)j; p++; } } } }
/*****************************************************************************/ // Computes the derived fields in the Huffman table structure. static void FixHuffTbl(ref HuffmanTable htbl) { int32 l; int32 i; uint32[] bitMask = { 0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff, 0x0fffffff, 0x07ffffff, 0x03ffffff, 0x01ffffff, 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff, 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff, 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff, 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f, 0x0000000f, 0x00000007, 0x00000003, 0x00000001 }; // Figure C.1: make table of Huffman code length for each symbol // Note that this is in code-length order. int8[] huffsize = new int8[257]; int32 p = 0; for (l = 1; l <= 16; l++) { for (i = 1; i <= (int32)htbl.bits[l]; i++) { huffsize[p++] = (int8)l; } } huffsize[p] = 0; int32 lastp = p; // Figure C.2: generate the codes themselves // Note that this is in code-length order. uint16[] huffcode = new uint16[257]; uint16 code = 0; int32 si = huffsize[0]; p = 0; while (huffsize[p] != 0) { while (((int32)huffsize[p]) == si) { huffcode[p++] = code; code++; } code <<= 1; si++; } // Figure C.3: generate encoding tables // These are code and size indexed by symbol value // Set any codeless symbols to have code length 0; this allows // EmitBits to detect any attempt to emit such symbols. //memset(htbl->ehufsi, 0, sizeof(htbl->ehufsi)); htbl.ehufsi = new int8[htbl.ehufsi.Length]; for (p = 0; p < lastp; p++) { htbl.ehufco[htbl.huffval[p]] = huffcode[p]; htbl.ehufsi[htbl.huffval[p]] = huffsize[p]; } // Figure F.15: generate decoding tables p = 0; for (l = 1; l <= 16; l++) { if (htbl.bits[l] != 0) { htbl.valptr[l] = (int16)p; htbl.mincode[l] = huffcode[p]; p += htbl.bits[l]; htbl.maxcode[l] = huffcode[p - 1]; } else { htbl.maxcode[l] = -1; } } // We put in this value to ensure HuffDecode terminates. htbl.maxcode[17] = (int)0xFFFFFL; // Build the numbits, value lookup tables. // These table allow us to gather 8 bits from the bits stream, // and immediately lookup the size and value of the huffman codes. // If size is zero, it means that more than 8 bits are in the huffman // code (this happens about 3-4% of the time). //memset(htbl->numbits, 0, sizeof(htbl->numbits)); htbl.numbits = new int32[htbl.numbits.Length]; for (p = 0; p < lastp; p++) { int32 size = huffsize[p]; if (size <= 8) { int32 value = htbl.huffval[p]; code = huffcode[p]; int32 ll = code << (8 - size); int32 ul = (size < 8 ? (Int32)((uint32)ll | bitMask[24 + size]) : ll); if (ul >= (int32)htbl.numbits.Length || ul >= (Int32)htbl.value.Length) { //ThrowBadFormat(); // TODO see if I need to add this back in somehow } for (i = ll; i <= ul; i++) { htbl.numbits[i] = size; htbl.value[i] = value; } } } }