/// <summary> /// For handling dynamic Huffman codes. /// </summary> /// <returns>A sequence of <see cref="CodeTree" /> items.</returns> private CodeTree[] DecodeHuffmanCodes() { var numLitLenCodes = this.ReadInt(5) + 257; // hlit + 257 var numDistCodes = this.ReadInt(5) + 1; // hdist + 1 var numCodeLenCodes = this.ReadInt(4) + 4; // hclen + 4 var codeLenCodeLen = new int[19]; codeLenCodeLen[16] = this.ReadInt(3); codeLenCodeLen[17] = this.ReadInt(3); codeLenCodeLen[18] = this.ReadInt(3); codeLenCodeLen[0] = this.ReadInt(3); for (var i = 0; i < numCodeLenCodes - 4; i++) { if (i % 2 == 0) { codeLenCodeLen[8 + (i / 2)] = this.ReadInt(3); } else { codeLenCodeLen[7 - (i / 2)] = this.ReadInt(3); } } var codeLenCode = new CanonicalCode(codeLenCodeLen).ToCodeTree(); var codeLens = new int[numLitLenCodes + numDistCodes]; var runVal = -1; var runLen = 0; for (var i = 0; i < codeLens.Length; i++) { if (runLen > 0) { codeLens[i] = runVal; runLen--; } else { var sym = this.DecodeSymbol(codeLenCode); if (sym < 16) { codeLens[i] = sym; runVal = sym; } else { if (sym == 16) { if (runVal == -1) { throw new FormatException("No code length value to copy"); } runLen = this.ReadInt(2) + 3; } else if (sym == 17) { runVal = 0; runLen = this.ReadInt(3) + 3; } else if (sym == 18) { runVal = 0; runLen = this.ReadInt(7) + 11; } else { throw new Exception(); } i--; } } } if (runLen > 0) { throw new FormatException("Run exceeds number of codes"); } // Create code trees var litLenCodeLen = Arrays.CopyOf(codeLens, numLitLenCodes); var litLenCode = new CanonicalCode(litLenCodeLen).ToCodeTree(); var distCodeLen = Arrays.CopyOfRange(codeLens, numLitLenCodes, codeLens.Length); CodeTree distCode; if (distCodeLen.Length == 1 && distCodeLen[0] == 0) { distCode = null; // Empty distance code; the block shall be all literal symbols } else { distCode = new CanonicalCode(distCodeLen).ToCodeTree(); } return new[] { litLenCode, distCode }; }
/// <summary> /// For handling dynamic Huffman codes. /// </summary> /// <returns>A sequence of <see cref="CodeTree" /> items.</returns> private CodeTree[] DecodeHuffmanCodes() { var numLitLenCodes = this.ReadInt(5) + 257; // hlit + 257 var numDistCodes = this.ReadInt(5) + 1; // hdist + 1 var numCodeLenCodes = this.ReadInt(4) + 4; // hclen + 4 var codeLenCodeLen = new int[19]; codeLenCodeLen[16] = this.ReadInt(3); codeLenCodeLen[17] = this.ReadInt(3); codeLenCodeLen[18] = this.ReadInt(3); codeLenCodeLen[0] = this.ReadInt(3); for (var i = 0; i < numCodeLenCodes - 4; i++) { if (i % 2 == 0) { codeLenCodeLen[8 + (i / 2)] = this.ReadInt(3); } else { codeLenCodeLen[7 - (i / 2)] = this.ReadInt(3); } } var codeLenCode = new CanonicalCode(codeLenCodeLen).ToCodeTree(); var codeLens = new int[numLitLenCodes + numDistCodes]; var runVal = -1; var runLen = 0; for (var i = 0; i < codeLens.Length; i++) { if (runLen > 0) { codeLens[i] = runVal; runLen--; } else { var sym = this.DecodeSymbol(codeLenCode); if (sym < 16) { codeLens[i] = sym; runVal = sym; } else { if (sym == 16) { if (runVal == -1) { throw new FormatException("No code length value to copy"); } runLen = this.ReadInt(2) + 3; } else if (sym == 17) { runVal = 0; runLen = this.ReadInt(3) + 3; } else if (sym == 18) { runVal = 0; runLen = this.ReadInt(7) + 11; } else { throw new Exception(); } i--; } } } if (runLen > 0) { throw new FormatException("Run exceeds number of codes"); } // Create code trees var litLenCodeLen = Arrays.CopyOf(codeLens, numLitLenCodes); var litLenCode = new CanonicalCode(litLenCodeLen).ToCodeTree(); var distCodeLen = Arrays.CopyOfRange(codeLens, numLitLenCodes, codeLens.Length); CodeTree distCode; if (distCodeLen.Length == 1 && distCodeLen[0] == 0) { distCode = null; // Empty distance code; the block shall be all literal symbols } else { distCode = new CanonicalCode(distCodeLen).ToCodeTree(); } return(new[] { litLenCode, distCode }); }