PageRenderTime 42ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/MediaSage/ExternalAPIs/TheTVDB/TvdbLib/Zip/Compression/DeflaterHuffman.cs

#
C# | 974 lines | 655 code | 117 blank | 202 comment | 112 complexity | 703b806f65b655ff1ecd2be4e4ee3efd MD5 | raw file
Possible License(s): LGPL-2.1
  1. #region
  2. using System;
  3. #endregion
  4. namespace TvdbLib.SharpZipLib.Zip.Compression
  5. {
  6. ///<summary>
  7. /// This is the DeflaterHuffman class.
  8. ///
  9. /// This class is <i>not</i> thread safe. This is inherent in the API, due
  10. /// to the split of Deflate and SetInput.
  11. ///
  12. /// author of the original java version : Jochen Hoenicke
  13. ///</summary>
  14. public class DeflaterHuffman
  15. {
  16. #region Fields
  17. // Number of codes used to transfer bit lengths
  18. private const int BITLEN_NUM = 19;
  19. private const int BUFSIZE = 1 << (DeflaterConstants.DEFAULT_MEM_LEVEL + 6);
  20. // Number of distance codes
  21. private const int DIST_NUM = 30;
  22. private const int EOF_SYMBOL = 256;
  23. private const int LITERAL_NUM = 286;
  24. // repeat a zero length 11-138 times (7 bits of repeat count)
  25. private const int REP_11_138 = 18;
  26. // repeat a zero length 3-10 times (3 bits of repeat count)
  27. private const int REP_3_10 = 17;
  28. // repeat previous bit length 3-6 times (2 bits of repeat count)
  29. private const int REP_3_6 = 16;
  30. private static readonly byte[] bit4Reverse =
  31. {
  32. 0,
  33. 8,
  34. 4,
  35. 12,
  36. 2,
  37. 10,
  38. 6,
  39. 14,
  40. 1,
  41. 9,
  42. 5,
  43. 13,
  44. 3,
  45. 11,
  46. 7,
  47. 15
  48. };
  49. // The lengths of the bit length codes are sent in order of decreasing
  50. // probability, to avoid transmitting the lengths for unused bit length codes.
  51. private static readonly int[] BL_ORDER = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
  52. private static readonly short[] staticDCodes;
  53. private static readonly byte[] staticDLength;
  54. private static readonly short[] staticLCodes;
  55. private static readonly byte[] staticLLength;
  56. private readonly Tree blTree;
  57. // Buffer for distances
  58. private readonly short[] d_buf;
  59. private readonly Tree distTree;
  60. private readonly byte[] l_buf;
  61. private readonly Tree literalTree;
  62. private int extra_bits;
  63. private int last_lit;
  64. /// <summary>
  65. /// Pending buffer to use
  66. /// </summary>
  67. public DeflaterPending pending;
  68. #endregion Fields
  69. #region Constructors
  70. static DeflaterHuffman()
  71. {
  72. // See RFC 1951 3.2.6
  73. // Literal codes
  74. staticLCodes = new short[LITERAL_NUM];
  75. staticLLength = new byte[LITERAL_NUM];
  76. int i = 0;
  77. while (i < 144)
  78. {
  79. staticLCodes[i] = BitReverse((0x030 + i) << 8);
  80. staticLLength[i++] = 8;
  81. }
  82. while (i < 256)
  83. {
  84. staticLCodes[i] = BitReverse((0x190 - 144 + i) << 7);
  85. staticLLength[i++] = 9;
  86. }
  87. while (i < 280)
  88. {
  89. staticLCodes[i] = BitReverse((0x000 - 256 + i) << 9);
  90. staticLLength[i++] = 7;
  91. }
  92. while (i < LITERAL_NUM)
  93. {
  94. staticLCodes[i] = BitReverse((0x0c0 - 280 + i) << 8);
  95. staticLLength[i++] = 8;
  96. }
  97. // Distance codes
  98. staticDCodes = new short[DIST_NUM];
  99. staticDLength = new byte[DIST_NUM];
  100. for (i = 0; i < DIST_NUM; i++)
  101. {
  102. staticDCodes[i] = BitReverse(i << 11);
  103. staticDLength[i] = 5;
  104. }
  105. }
  106. /// <summary>
  107. /// Construct instance with pending buffer
  108. /// </summary>
  109. /// <param name="pending"> Pending buffer to use </param>
  110. public DeflaterHuffman(DeflaterPending pending)
  111. {
  112. this.pending = pending;
  113. literalTree = new Tree(this, LITERAL_NUM, 257, 15);
  114. distTree = new Tree(this, DIST_NUM, 1, 15);
  115. blTree = new Tree(this, BITLEN_NUM, 4, 7);
  116. d_buf = new short[BUFSIZE];
  117. l_buf = new byte[BUFSIZE];
  118. }
  119. #endregion Constructors
  120. #region Methods
  121. /// <summary>
  122. /// Reverse the bits of a 16 bit value.
  123. /// </summary>
  124. /// <param name="toReverse"> Value to reverse bits </param>
  125. /// <returns> Value with bits reversed </returns>
  126. public static short BitReverse(int toReverse)
  127. {
  128. return (short) (bit4Reverse[toReverse & 0xF] << 12 |
  129. bit4Reverse[(toReverse >> 4) & 0xF] << 8 |
  130. bit4Reverse[(toReverse >> 8) & 0xF] << 4 |
  131. bit4Reverse[toReverse >> 12]);
  132. }
  133. /// <summary>
  134. /// Compress current buffer writing data to pending buffer
  135. /// </summary>
  136. public void CompressBlock()
  137. {
  138. for (int i = 0; i < last_lit; i++)
  139. {
  140. int litlen = l_buf[i] & 0xff;
  141. int dist = d_buf[i];
  142. if (dist-- != 0)
  143. {
  144. // if (DeflaterConstants.DEBUGGING) {
  145. // Console.Write("["+(dist+1)+","+(litlen+3)+"]: ");
  146. // }
  147. int lc = Lcode(litlen);
  148. literalTree.WriteSymbol(lc);
  149. int bits = (lc - 261)/4;
  150. if (bits > 0 && bits <= 5)
  151. {
  152. pending.WriteBits(litlen & ((1 << bits) - 1), bits);
  153. }
  154. int dc = Dcode(dist);
  155. distTree.WriteSymbol(dc);
  156. bits = dc/2 - 1;
  157. if (bits > 0)
  158. {
  159. pending.WriteBits(dist & ((1 << bits) - 1), bits);
  160. }
  161. }
  162. else
  163. {
  164. // if (DeflaterConstants.DEBUGGING) {
  165. // if (litlen > 32 && litlen < 127) {
  166. // Console.Write("("+(char)litlen+"): ");
  167. // } else {
  168. // Console.Write("{"+litlen+"}: ");
  169. // }
  170. // }
  171. literalTree.WriteSymbol(litlen);
  172. }
  173. }
  174. #if DebugDeflation
  175. if (DeflaterConstants.DEBUGGING) {
  176. Console.Write("EOF: ");
  177. }
  178. #endif
  179. literalTree.WriteSymbol(EOF_SYMBOL);
  180. #if DebugDeflation
  181. if (DeflaterConstants.DEBUGGING) {
  182. literalTree.CheckEmpty();
  183. distTree.CheckEmpty();
  184. }
  185. #endif
  186. }
  187. /// <summary>
  188. /// Flush block to output with compression
  189. /// </summary>
  190. /// <param name="stored"> Data to flush </param>
  191. /// <param name="storedOffset"> Index of first byte to flush </param>
  192. /// <param name="storedLength"> Count of bytes to flush </param>
  193. /// <param name="lastBlock"> True if this is the last block </param>
  194. public void FlushBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
  195. {
  196. literalTree.freqs[EOF_SYMBOL]++;
  197. // Build trees
  198. literalTree.BuildTree();
  199. distTree.BuildTree();
  200. // Calculate bitlen frequency
  201. literalTree.CalcBLFreq(blTree);
  202. distTree.CalcBLFreq(blTree);
  203. // Build bitlen tree
  204. blTree.BuildTree();
  205. int blTreeCodes = 4;
  206. for (int i = 18; i > blTreeCodes; i--)
  207. {
  208. if (blTree.length[BL_ORDER[i]] > 0)
  209. {
  210. blTreeCodes = i + 1;
  211. }
  212. }
  213. int opt_len = 14 + blTreeCodes*3 + blTree.GetEncodedLength() +
  214. literalTree.GetEncodedLength() + distTree.GetEncodedLength() +
  215. extra_bits;
  216. int static_len = extra_bits;
  217. for (int i = 0; i < LITERAL_NUM; i++)
  218. {
  219. static_len += literalTree.freqs[i]*staticLLength[i];
  220. }
  221. for (int i = 0; i < DIST_NUM; i++)
  222. {
  223. static_len += distTree.freqs[i]*staticDLength[i];
  224. }
  225. if (opt_len >= static_len)
  226. {
  227. // Force static trees
  228. opt_len = static_len;
  229. }
  230. if (storedOffset >= 0 && storedLength + 4 < opt_len >> 3)
  231. {
  232. // Store Block
  233. // if (DeflaterConstants.DEBUGGING) {
  234. // //Console.WriteLine("Storing, since " + storedLength + " < " + opt_len
  235. // + " <= " + static_len);
  236. // }
  237. FlushStoredBlock(stored, storedOffset, storedLength, lastBlock);
  238. }
  239. else if (opt_len == static_len)
  240. {
  241. // Encode with static tree
  242. pending.WriteBits((DeflaterConstants.STATIC_TREES << 1) + (lastBlock ? 1 : 0), 3);
  243. literalTree.SetStaticCodes(staticLCodes, staticLLength);
  244. distTree.SetStaticCodes(staticDCodes, staticDLength);
  245. CompressBlock();
  246. Reset();
  247. }
  248. else
  249. {
  250. // Encode with dynamic tree
  251. pending.WriteBits((DeflaterConstants.DYN_TREES << 1) + (lastBlock ? 1 : 0), 3);
  252. SendAllTrees(blTreeCodes);
  253. CompressBlock();
  254. Reset();
  255. }
  256. }
  257. /// <summary>
  258. /// Flush block to output with no compression
  259. /// </summary>
  260. /// <param name="stored"> Data to write </param>
  261. /// <param name="storedOffset"> Index of first byte to write </param>
  262. /// <param name="storedLength"> Count of bytes to write </param>
  263. /// <param name="lastBlock"> True if this is the last block </param>
  264. public void FlushStoredBlock(byte[] stored, int storedOffset, int storedLength, bool lastBlock)
  265. {
  266. #if DebugDeflation
  267. // if (DeflaterConstants.DEBUGGING) {
  268. // //Console.WriteLine("Flushing stored block "+ storedLength);
  269. // }
  270. #endif
  271. pending.WriteBits((DeflaterConstants.STORED_BLOCK << 1) + (lastBlock ? 1 : 0), 3);
  272. pending.AlignToByte();
  273. pending.WriteShort(storedLength);
  274. pending.WriteShort(~storedLength);
  275. pending.WriteBlock(stored, storedOffset, storedLength);
  276. Reset();
  277. }
  278. /// <summary>
  279. /// Get value indicating if internal buffer is full
  280. /// </summary>
  281. /// <returns> true if buffer is full </returns>
  282. public bool IsFull()
  283. {
  284. return last_lit >= BUFSIZE;
  285. }
  286. /// <summary>
  287. /// Reset internal state
  288. /// </summary>
  289. public void Reset()
  290. {
  291. last_lit = 0;
  292. extra_bits = 0;
  293. literalTree.Reset();
  294. distTree.Reset();
  295. blTree.Reset();
  296. }
  297. /// <summary>
  298. /// Write all trees to pending buffer
  299. /// </summary>
  300. /// <param name="blTreeCodes"> The number/rank of treecodes to send. </param>
  301. public void SendAllTrees(int blTreeCodes)
  302. {
  303. blTree.BuildCodes();
  304. literalTree.BuildCodes();
  305. distTree.BuildCodes();
  306. pending.WriteBits(literalTree.numCodes - 257, 5);
  307. pending.WriteBits(distTree.numCodes - 1, 5);
  308. pending.WriteBits(blTreeCodes - 4, 4);
  309. for (int rank = 0; rank < blTreeCodes; rank++)
  310. {
  311. pending.WriteBits(blTree.length[BL_ORDER[rank]], 3);
  312. }
  313. literalTree.WriteTree(blTree);
  314. distTree.WriteTree(blTree);
  315. #if DebugDeflation
  316. if (DeflaterConstants.DEBUGGING) {
  317. blTree.CheckEmpty();
  318. }
  319. #endif
  320. }
  321. /// <summary>
  322. /// Add distance code and length to literal and distance trees
  323. /// </summary>
  324. /// <param name="distance"> Distance code </param>
  325. /// <param name="length"> Length </param>
  326. /// <returns> Value indicating if internal buffer is full </returns>
  327. public bool TallyDist(int distance, int length)
  328. {
  329. // if (DeflaterConstants.DEBUGGING) {
  330. // //Console.WriteLine("[" + distance + "," + length + "]");
  331. // }
  332. d_buf[last_lit] = (short) distance;
  333. l_buf[last_lit++] = (byte) (length - 3);
  334. int lc = Lcode(length - 3);
  335. literalTree.freqs[lc]++;
  336. if (lc >= 265 && lc < 285)
  337. {
  338. extra_bits += (lc - 261)/4;
  339. }
  340. int dc = Dcode(distance - 1);
  341. distTree.freqs[dc]++;
  342. if (dc >= 4)
  343. {
  344. extra_bits += dc/2 - 1;
  345. }
  346. return IsFull();
  347. }
  348. /// <summary>
  349. /// Add literal to buffer
  350. /// </summary>
  351. /// <param name="literal"> Literal value to add to buffer. </param>
  352. /// <returns> Value indicating internal buffer is full </returns>
  353. public bool TallyLit(int literal)
  354. {
  355. // if (DeflaterConstants.DEBUGGING) {
  356. // if (lit > 32 && lit < 127) {
  357. // //Console.WriteLine("("+(char)lit+")");
  358. // } else {
  359. // //Console.WriteLine("{"+lit+"}");
  360. // }
  361. // }
  362. d_buf[last_lit] = 0;
  363. l_buf[last_lit++] = (byte) literal;
  364. literalTree.freqs[literal]++;
  365. return IsFull();
  366. }
  367. private static int Dcode(int distance)
  368. {
  369. int code = 0;
  370. while (distance >= 4)
  371. {
  372. code += 2;
  373. distance >>= 1;
  374. }
  375. return code + distance;
  376. }
  377. private static int Lcode(int length)
  378. {
  379. if (length == 255)
  380. {
  381. return 285;
  382. }
  383. int code = 257;
  384. while (length >= 8)
  385. {
  386. code += 4;
  387. length >>= 1;
  388. }
  389. return code + length;
  390. }
  391. #endregion Methods
  392. #region Nested Types
  393. private class Tree
  394. {
  395. #region Fields
  396. private readonly int[] bl_counts;
  397. private readonly DeflaterHuffman dh;
  398. public readonly short[] freqs;
  399. private readonly int maxLength;
  400. public readonly int minNumCodes;
  401. private short[] codes;
  402. public byte[] length;
  403. public int numCodes;
  404. #endregion Fields
  405. #region Constructors
  406. public Tree(DeflaterHuffman dh, int elems, int minCodes, int maxLength)
  407. {
  408. this.dh = dh;
  409. minNumCodes = minCodes;
  410. this.maxLength = maxLength;
  411. freqs = new short[elems];
  412. bl_counts = new int[maxLength];
  413. }
  414. #endregion Constructors
  415. #region Methods
  416. /// <summary>
  417. /// Build dynamic codes and lengths
  418. /// </summary>
  419. public void BuildCodes()
  420. {
  421. int numSymbols = freqs.Length;
  422. var nextCode = new int[maxLength];
  423. int code = 0;
  424. codes = new short[freqs.Length];
  425. // if (DeflaterConstants.DEBUGGING) {
  426. // //Console.WriteLine("buildCodes: "+freqs.Length);
  427. // }
  428. for (int bits = 0; bits < maxLength; bits++)
  429. {
  430. nextCode[bits] = code;
  431. code += bl_counts[bits] << (15 - bits);
  432. // if (DeflaterConstants.DEBUGGING) {
  433. // //Console.WriteLine("bits: " + ( bits + 1) + " count: " + bl_counts[bits]
  434. // +" nextCode: "+code);
  435. // }
  436. }
  437. #if DebugDeflation
  438. if ( DeflaterConstants.DEBUGGING && (code != 65536) )
  439. {
  440. throw new SharpZipBaseException("Inconsistent bl_counts!");
  441. }
  442. #endif
  443. for (int i = 0; i < numCodes; i++)
  444. {
  445. int bits = length[i];
  446. if (bits > 0)
  447. {
  448. // if (DeflaterConstants.DEBUGGING) {
  449. // //Console.WriteLine("codes["+i+"] = rev(" + nextCode[bits-1]+"),
  450. // +bits);
  451. // }
  452. codes[i] = BitReverse(nextCode[bits - 1]);
  453. nextCode[bits - 1] += 1 << (16 - bits);
  454. }
  455. }
  456. }
  457. public void BuildTree()
  458. {
  459. int numSymbols = freqs.Length;
  460. /* heap is a priority queue, sorted by frequency, least frequent
  461. * nodes first. The heap is a binary tree, with the property, that
  462. * the parent node is smaller than both child nodes. This assures
  463. * that the smallest node is the first parent.
  464. *
  465. * The binary tree is encoded in an array: 0 is root node and
  466. * the nodes 2*n+1, 2*n+2 are the child nodes of node n.
  467. */
  468. var heap = new int[numSymbols];
  469. int heapLen = 0;
  470. int maxCode = 0;
  471. for (int n = 0; n < numSymbols; n++)
  472. {
  473. int freq = freqs[n];
  474. if (freq != 0)
  475. {
  476. // Insert n into heap
  477. int pos = heapLen++;
  478. int ppos;
  479. while (pos > 0 && freqs[heap[ppos = (pos - 1)/2]] > freq)
  480. {
  481. heap[pos] = heap[ppos];
  482. pos = ppos;
  483. }
  484. heap[pos] = n;
  485. maxCode = n;
  486. }
  487. }
  488. /* We could encode a single literal with 0 bits but then we
  489. * don't see the literals. Therefore we force at least two
  490. * literals to avoid this case. We don't care about order in
  491. * this case, both literals get a 1 bit code.
  492. */
  493. while (heapLen < 2)
  494. {
  495. int node = maxCode < 2 ? ++maxCode : 0;
  496. heap[heapLen++] = node;
  497. }
  498. numCodes = Math.Max(maxCode + 1, minNumCodes);
  499. int numLeafs = heapLen;
  500. var childs = new int[4*heapLen - 2];
  501. var values = new int[2*heapLen - 1];
  502. int numNodes = numLeafs;
  503. for (int i = 0; i < heapLen; i++)
  504. {
  505. int node = heap[i];
  506. childs[2*i] = node;
  507. childs[2*i + 1] = -1;
  508. values[i] = freqs[node] << 8;
  509. heap[i] = i;
  510. }
  511. /* Construct the Huffman tree by repeatedly combining the least two
  512. * frequent nodes.
  513. */
  514. do
  515. {
  516. int first = heap[0];
  517. int last = heap[--heapLen];
  518. // Propagate the hole to the leafs of the heap
  519. int ppos = 0;
  520. int path = 1;
  521. while (path < heapLen)
  522. {
  523. if (path + 1 < heapLen && values[heap[path]] > values[heap[path + 1]])
  524. {
  525. path++;
  526. }
  527. heap[ppos] = heap[path];
  528. ppos = path;
  529. path = path*2 + 1;
  530. }
  531. /* Now propagate the last element down along path. Normally
  532. * it shouldn't go too deep.
  533. */
  534. int lastVal = values[last];
  535. while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal)
  536. {
  537. heap[path] = heap[ppos];
  538. }
  539. heap[path] = last;
  540. int second = heap[0];
  541. // Create a new node father of first and second
  542. last = numNodes++;
  543. childs[2*last] = first;
  544. childs[2*last + 1] = second;
  545. int mindepth = Math.Min(values[first] & 0xff, values[second] & 0xff);
  546. values[last] = lastVal = values[first] + values[second] - mindepth + 1;
  547. // Again, propagate the hole to the leafs
  548. ppos = 0;
  549. path = 1;
  550. while (path < heapLen)
  551. {
  552. if (path + 1 < heapLen && values[heap[path]] > values[heap[path + 1]])
  553. {
  554. path++;
  555. }
  556. heap[ppos] = heap[path];
  557. ppos = path;
  558. path = ppos*2 + 1;
  559. }
  560. // Now propagate the new element down along path
  561. while ((path = ppos) > 0 && values[heap[ppos = (path - 1)/2]] > lastVal)
  562. {
  563. heap[path] = heap[ppos];
  564. }
  565. heap[path] = last;
  566. } while (heapLen > 1);
  567. if (heap[0] != childs.Length/2 - 1)
  568. {
  569. throw new SharpZipBaseException("Heap invariant violated");
  570. }
  571. BuildLength(childs);
  572. }
  573. /// <summary>
  574. /// Scan a literal or distance tree to determine the frequencies of the codes
  575. /// in the bit length tree.
  576. /// </summary>
  577. public void CalcBLFreq(Tree blTree)
  578. {
  579. int max_count; /* max repeat count */
  580. int min_count; /* min repeat count */
  581. int count; /* repeat count of the current code */
  582. int curlen = -1; /* length of current code */
  583. int i = 0;
  584. while (i < numCodes)
  585. {
  586. count = 1;
  587. int nextlen = length[i];
  588. if (nextlen == 0)
  589. {
  590. max_count = 138;
  591. min_count = 3;
  592. }
  593. else
  594. {
  595. max_count = 6;
  596. min_count = 3;
  597. if (curlen != nextlen)
  598. {
  599. blTree.freqs[nextlen]++;
  600. count = 0;
  601. }
  602. }
  603. curlen = nextlen;
  604. i++;
  605. while (i < numCodes && curlen == length[i])
  606. {
  607. i++;
  608. if (++count >= max_count)
  609. {
  610. break;
  611. }
  612. }
  613. if (count < min_count)
  614. {
  615. blTree.freqs[curlen] += (short) count;
  616. }
  617. else if (curlen != 0)
  618. {
  619. blTree.freqs[REP_3_6]++;
  620. }
  621. else if (count <= 10)
  622. {
  623. blTree.freqs[REP_3_10]++;
  624. }
  625. else
  626. {
  627. blTree.freqs[REP_11_138]++;
  628. }
  629. }
  630. }
  631. /// <summary>
  632. /// Check that all frequencies are zero
  633. /// </summary>
  634. /// <exception cref="SharpZipBaseException">At least one frequency is non-zero</exception>
  635. public void CheckEmpty()
  636. {
  637. bool empty = true;
  638. for (int i = 0; i < freqs.Length; i++)
  639. {
  640. if (freqs[i] != 0)
  641. {
  642. //Console.WriteLine("freqs[" + i + "] == " + freqs[i]);
  643. empty = false;
  644. }
  645. }
  646. if (!empty)
  647. {
  648. throw new SharpZipBaseException("!Empty");
  649. }
  650. }
  651. /// <summary>
  652. /// Get encoded length
  653. /// </summary>
  654. /// <returns> Encoded length, the sum of frequencies * lengths </returns>
  655. public int GetEncodedLength()
  656. {
  657. int len = 0;
  658. for (int i = 0; i < freqs.Length; i++)
  659. {
  660. len += freqs[i]*length[i];
  661. }
  662. return len;
  663. }
  664. /// <summary>
  665. /// Resets the internal state of the tree
  666. /// </summary>
  667. public void Reset()
  668. {
  669. for (int i = 0; i < freqs.Length; i++)
  670. {
  671. freqs[i] = 0;
  672. }
  673. codes = null;
  674. length = null;
  675. }
  676. /// <summary>
  677. /// Set static codes and length
  678. /// </summary>
  679. /// <param name="staticCodes"> new codes </param>
  680. /// <param name="staticLengths"> length for new codes </param>
  681. public void SetStaticCodes(short[] staticCodes, byte[] staticLengths)
  682. {
  683. codes = staticCodes;
  684. length = staticLengths;
  685. }
  686. public void WriteSymbol(int code)
  687. {
  688. // if (DeflaterConstants.DEBUGGING) {
  689. // freqs[code]--;
  690. // // Console.Write("writeSymbol("+freqs.length+","+code+"): ");
  691. // }
  692. dh.pending.WriteBits(codes[code] & 0xffff, length[code]);
  693. }
  694. /// <summary>
  695. /// Write tree values
  696. /// </summary>
  697. /// <param name="blTree"> Tree to write </param>
  698. public void WriteTree(Tree blTree)
  699. {
  700. int max_count; // max repeat count
  701. int min_count; // min repeat count
  702. int count; // repeat count of the current code
  703. int curlen = -1; // length of current code
  704. int i = 0;
  705. while (i < numCodes)
  706. {
  707. count = 1;
  708. int nextlen = length[i];
  709. if (nextlen == 0)
  710. {
  711. max_count = 138;
  712. min_count = 3;
  713. }
  714. else
  715. {
  716. max_count = 6;
  717. min_count = 3;
  718. if (curlen != nextlen)
  719. {
  720. blTree.WriteSymbol(nextlen);
  721. count = 0;
  722. }
  723. }
  724. curlen = nextlen;
  725. i++;
  726. while (i < numCodes && curlen == length[i])
  727. {
  728. i++;
  729. if (++count >= max_count)
  730. {
  731. break;
  732. }
  733. }
  734. if (count < min_count)
  735. {
  736. while (count-- > 0)
  737. {
  738. blTree.WriteSymbol(curlen);
  739. }
  740. }
  741. else if (curlen != 0)
  742. {
  743. blTree.WriteSymbol(REP_3_6);
  744. dh.pending.WriteBits(count - 3, 2);
  745. }
  746. else if (count <= 10)
  747. {
  748. blTree.WriteSymbol(REP_3_10);
  749. dh.pending.WriteBits(count - 3, 3);
  750. }
  751. else
  752. {
  753. blTree.WriteSymbol(REP_11_138);
  754. dh.pending.WriteBits(count - 11, 7);
  755. }
  756. }
  757. }
  758. private void BuildLength(int[] childs)
  759. {
  760. length = new byte[freqs.Length];
  761. int numNodes = childs.Length/2;
  762. int numLeafs = (numNodes + 1)/2;
  763. int overflow = 0;
  764. for (int i = 0; i < maxLength; i++)
  765. {
  766. bl_counts[i] = 0;
  767. }
  768. // First calculate optimal bit lengths
  769. var lengths = new int[numNodes];
  770. lengths[numNodes - 1] = 0;
  771. for (int i = numNodes - 1; i >= 0; i--)
  772. {
  773. if (childs[2*i + 1] != -1)
  774. {
  775. int bitLength = lengths[i] + 1;
  776. if (bitLength > maxLength)
  777. {
  778. bitLength = maxLength;
  779. overflow++;
  780. }
  781. lengths[childs[2*i]] = lengths[childs[2*i + 1]] = bitLength;
  782. }
  783. else
  784. {
  785. // A leaf node
  786. int bitLength = lengths[i];
  787. bl_counts[bitLength - 1]++;
  788. length[childs[2*i]] = (byte) lengths[i];
  789. }
  790. }
  791. // if (DeflaterConstants.DEBUGGING) {
  792. // //Console.WriteLine("Tree "+freqs.Length+" lengths:");
  793. // for (int i=0; i < numLeafs; i++) {
  794. // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
  795. // + " len: "+length[childs[2*i]]);
  796. // }
  797. // }
  798. if (overflow == 0)
  799. {
  800. return;
  801. }
  802. int incrBitLen = maxLength - 1;
  803. do
  804. {
  805. // Find the first bit length which could increase:
  806. while (bl_counts[--incrBitLen] == 0)
  807. ;
  808. // Move this node one down and remove a corresponding
  809. // number of overflow nodes.
  810. do
  811. {
  812. bl_counts[incrBitLen]--;
  813. bl_counts[++incrBitLen]++;
  814. overflow -= 1 << (maxLength - 1 - incrBitLen);
  815. } while (overflow > 0 && incrBitLen < maxLength - 1);
  816. } while (overflow > 0);
  817. /* We may have overshot above. Move some nodes from maxLength to
  818. * maxLength-1 in that case.
  819. */
  820. bl_counts[maxLength - 1] += overflow;
  821. bl_counts[maxLength - 2] -= overflow;
  822. /* Now recompute all bit lengths, scanning in increasing
  823. * frequency. It is simpler to reconstruct all lengths instead of
  824. * fixing only the wrong ones. This idea is taken from 'ar'
  825. * written by Haruhiko Okumura.
  826. *
  827. * The nodes were inserted with decreasing frequency into the childs
  828. * array.
  829. */
  830. int nodePtr = 2*numLeafs;
  831. for (int bits = maxLength; bits != 0; bits--)
  832. {
  833. int n = bl_counts[bits - 1];
  834. while (n > 0)
  835. {
  836. int childPtr = 2*childs[nodePtr++];
  837. if (childs[childPtr + 1] == -1)
  838. {
  839. // We found another leaf
  840. length[childs[childPtr]] = (byte) bits;
  841. n--;
  842. }
  843. }
  844. }
  845. // if (DeflaterConstants.DEBUGGING) {
  846. // //Console.WriteLine("*** After overflow elimination. ***");
  847. // for (int i=0; i < numLeafs; i++) {
  848. // //Console.WriteLine("Node "+childs[2*i]+" freq: "+freqs[childs[2*i]]
  849. // + " len: "+length[childs[2*i]]);
  850. // }
  851. // }
  852. }
  853. #endregion Methods
  854. }
  855. #endregion Nested Types
  856. }
  857. }