/*****************************************************************************/

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