PageRenderTime 62ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/Utilities/Compression/Deflaters/DeflaterHuffman.cs

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