Ejemplo n.º 1
0
        /// If the size of the code is larger than two, we must transmit the length
        /// of every symbol in the code. To save space, the lengths are themselves
        /// Huffman-coded with a length code, so the lengths of the length code must
        /// be stored first.
        static void WriteNormalCodeLengths(BitWriter b, List <Huffman.Code> codes)
        {
            var encodedLengths = EncodeCodeLengths(codes);
            var lengthHisto    = new Histogram(19);

            for (int i = 0; i < encodedLengths.Count; ++i)
            {
                int sym = encodedLengths[i];
                lengthHisto.Hit(sym);
                if (sym >= 16)
                {
                    i += 1;
                }
            }
            var lengthCodes = Huffman.BuildCodes(lengthHisto, 7);

            int lengthCodeCount = 0;

            for (int i = 0; i < 19; ++i)
            {
                if (lengthHisto[CODE_LENGTH_ORDER[i]] > 0)
                {
                    lengthCodeCount = i + 1;
                }
            }
            if (lengthCodeCount < 4)
            {
                lengthCodeCount = 4;
            }

            b.WriteBits(0, 1);
            b.WriteBits(lengthCodeCount - 4, 4);
            for (int i = 0; i < lengthCodeCount; ++i)
            {
                b.WriteBits(lengthCodes[CODE_LENGTH_ORDER[i]].Length, 3);
            }

            b.WriteBits(0, 1);
            for (int i = 0; i < encodedLengths.Count; ++i)
            {
                int sym = encodedLengths[i];
                b.WriteCode(lengthCodes[sym]);
                if (sym == 16)
                {
                    b.WriteBits(encodedLengths[++i], 2);
                }
                else if (sym == 17)
                {
                    b.WriteBits(encodedLengths[++i], 3);
                }
                else if (sym == 18)
                {
                    b.WriteBits(encodedLengths[++i], 7);
                }
            }
        }
Ejemplo n.º 2
0
        /// Encodes the image into entropy-coded bitstream. The isRecursive flag
        /// must be true iff the data represents the main ARGB image.
        internal static void WriteImageData(BitWriter b, Image image,
                                            bool isRecursive, int colorCacheBits = 0)
        {
            if (colorCacheBits > 0)
            {
                if (colorCacheBits > 11)
                {
                    throw new ArgumentException("Too many color cache bits");
                }
                b.WriteBits(1, 1);
                b.WriteBits(colorCacheBits, 4);
            }
            else
            {
                b.WriteBits(0, 1);
            }

            if (isRecursive)
            {
                b.WriteBits(0, 1); // no meta-Huffman image
            }

            var encoded = EncodeImageData(image, colorCacheBits);
            var histos  = new List <Histogram> {
                new Histogram(256 + 24 + (colorCacheBits > 0 ? (1 << colorCacheBits) : 0)),
                new Histogram(256),
                new Histogram(256),
                new Histogram(256),
                new Histogram(40),
            };

            for (int i = 0; i < encoded.Count; ++i)
            {
                histos[0].Hit(encoded[i]);
                if (encoded[i] < 256)
                {
                    histos[1].Hit(encoded[i + 1]);
                    histos[2].Hit(encoded[i + 2]);
                    histos[3].Hit(encoded[i + 3]);
                    i += 3;
                }
                else if (encoded[i] < 256 + 24)
                {
                    histos[4].Hit(encoded[i + 2]);
                    i += 3;
                }
            }

            var codess = new List <List <Huffman.Code> >();

            for (int i = 0; i < 5; ++i)
            {
                var codes = Huffman.BuildCodes(histos[i], 16);
                CodeLengths.WriteCodeLengths(b, codes);
                codess.Add(codes);
            }

            for (int i = 0; i < encoded.Count; ++i)
            {
                b.WriteCode(codess[0][encoded[i]]);
                if (encoded[i] < 256)
                {
                    b.WriteCode(codess[1][encoded[i + 1]]);
                    b.WriteCode(codess[2][encoded[i + 2]]);
                    b.WriteCode(codess[3][encoded[i + 3]]);
                    i += 3;
                }
                else if (encoded[i] < 256 + 24)
                {
                    b.WriteBits(encoded[i + 1], ExtraBitsCount(encoded[i] - 256));
                    b.WriteCode(codess[4][encoded[i + 2]]);
                    b.WriteBits(encoded[i + 3], ExtraBitsCount(encoded[i + 2]));
                    i += 3;
                }
            }
        }