/// Encodes the image as a raw VP8L bitstream. static void WriteImageBitstream(BitWriter b, Image image) { var analysis = Analysis.AnalyzeImage(image); WriteHeader(b, image.Width, image.Height, analysis.HasAlpha); if (analysis.PaletteOrNull != null) { image = Transform.PaletteTransform(b, image, analysis.PaletteOrNull); } if (analysis.UseSubtractGreen) { image = Transform.SubtractGreenTransform(b, image); } if (analysis.UsePredict) { image = Transform.PredictTransform(b, image); } b.WriteBits(0, 1); ImageData.WriteImageData(b, image, true, analysis.ColorCacheBits); }
/// 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; } } }