/// <summary> /// Get the actual bit values for a tree of bit depths. /// </summary> /// <param name="tree">The huffman tree.</param> private static void ConvertBitDepthsToSymbols(HuffmanTreeCode tree) { // 0 bit-depth means that the symbol does not exist. uint[] nextCode = new uint[WebpConstants.MaxAllowedCodeLength + 1]; int[] depthCount = new int[WebpConstants.MaxAllowedCodeLength + 1]; int len = tree.NumSymbols; for (int i = 0; i < len; i++) { int codeLength = tree.CodeLengths[i]; depthCount[codeLength]++; } depthCount[0] = 0; // ignore unused symbol. nextCode[0] = 0; uint code = 0; for (int i = 1; i <= WebpConstants.MaxAllowedCodeLength; i++) { code = (uint)((code + depthCount[i - 1]) << 1); nextCode[i] = code; } for (int i = 0; i < len; i++) { int codeLength = tree.CodeLengths[i]; tree.Codes[i] = (short)ReverseBits(codeLength, nextCode[codeLength]++); } }
public static int CreateCompressedHuffmanTree(HuffmanTreeCode tree, HuffmanTreeToken[] tokensArray) { int depthSize = tree.NumSymbols; int prevValue = 8; // 8 is the initial value for rle. int i = 0; int tokenPos = 0; while (i < depthSize) { int value = tree.CodeLengths[i]; int k = i + 1; while (k < depthSize && tree.CodeLengths[k] == value) { k++; } int runs = k - i; if (value == 0) { tokenPos += CodeRepeatedZeros(runs, tokensArray.AsSpan(tokenPos)); } else { tokenPos += CodeRepeatedValues(runs, tokensArray.AsSpan(tokenPos), value, prevValue); prevValue = value; } i += runs; } return(tokenPos); }
public static void CreateHuffmanTree(uint[] histogram, int treeDepthLimit, bool[] bufRle, HuffmanTree[] huffTree, HuffmanTreeCode huffCode) { int numSymbols = huffCode.NumSymbols; bufRle.AsSpan().Clear(); OptimizeHuffmanForRle(numSymbols, bufRle, histogram); GenerateOptimalTree(huffTree, histogram, numSymbols, treeDepthLimit, huffCode.CodeLengths); // Create the actual bit codes for the bit lengths. ConvertBitDepthsToSymbols(huffCode); }