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