lzw.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. "use strict";
  2. var __importDefault = (this && this.__importDefault) || function (mod) {
  3. return (mod && mod.__esModule) ? mod : { "default": mod };
  4. };
  5. Object.defineProperty(exports, "__esModule", { value: true });
  6. const basedecoder_js_1 = __importDefault(require("./basedecoder.js"));
  7. const MIN_BITS = 9;
  8. const CLEAR_CODE = 256; // clear code
  9. const EOI_CODE = 257; // end of information
  10. const MAX_BYTELENGTH = 12;
  11. function getByte(array, position, length) {
  12. const d = position % 8;
  13. const a = Math.floor(position / 8);
  14. const de = 8 - d;
  15. const ef = (position + length) - ((a + 1) * 8);
  16. let fg = (8 * (a + 2)) - (position + length);
  17. const dg = ((a + 2) * 8) - position;
  18. fg = Math.max(0, fg);
  19. if (a >= array.length) {
  20. console.warn('ran off the end of the buffer before finding EOI_CODE (end on input code)');
  21. return EOI_CODE;
  22. }
  23. let chunk1 = array[a] & ((2 ** (8 - d)) - 1);
  24. chunk1 <<= (length - de);
  25. let chunks = chunk1;
  26. if (a + 1 < array.length) {
  27. let chunk2 = array[a + 1] >>> fg;
  28. chunk2 <<= Math.max(0, (length - dg));
  29. chunks += chunk2;
  30. }
  31. if (ef > 8 && a + 2 < array.length) {
  32. const hi = ((a + 3) * 8) - (position + length);
  33. const chunk3 = array[a + 2] >>> hi;
  34. chunks += chunk3;
  35. }
  36. return chunks;
  37. }
  38. function appendReversed(dest, source) {
  39. for (let i = source.length - 1; i >= 0; i--) {
  40. dest.push(source[i]);
  41. }
  42. return dest;
  43. }
  44. function decompress(input) {
  45. const dictionaryIndex = new Uint16Array(4093);
  46. const dictionaryChar = new Uint8Array(4093);
  47. for (let i = 0; i <= 257; i++) {
  48. dictionaryIndex[i] = 4096;
  49. dictionaryChar[i] = i;
  50. }
  51. let dictionaryLength = 258;
  52. let byteLength = MIN_BITS;
  53. let position = 0;
  54. function initDictionary() {
  55. dictionaryLength = 258;
  56. byteLength = MIN_BITS;
  57. }
  58. function getNext(array) {
  59. const byte = getByte(array, position, byteLength);
  60. position += byteLength;
  61. return byte;
  62. }
  63. function addToDictionary(i, c) {
  64. dictionaryChar[dictionaryLength] = c;
  65. dictionaryIndex[dictionaryLength] = i;
  66. dictionaryLength++;
  67. return dictionaryLength - 1;
  68. }
  69. function getDictionaryReversed(n) {
  70. const rev = [];
  71. for (let i = n; i !== 4096; i = dictionaryIndex[i]) {
  72. rev.push(dictionaryChar[i]);
  73. }
  74. return rev;
  75. }
  76. const result = [];
  77. initDictionary();
  78. const array = new Uint8Array(input);
  79. let code = getNext(array);
  80. let oldCode;
  81. while (code !== EOI_CODE) {
  82. if (code === CLEAR_CODE) {
  83. initDictionary();
  84. code = getNext(array);
  85. while (code === CLEAR_CODE) {
  86. code = getNext(array);
  87. }
  88. if (code === EOI_CODE) {
  89. break;
  90. }
  91. else if (code > CLEAR_CODE) {
  92. throw new Error(`corrupted code at scanline ${code}`);
  93. }
  94. else {
  95. const val = getDictionaryReversed(code);
  96. appendReversed(result, val);
  97. oldCode = code;
  98. }
  99. }
  100. else if (code < dictionaryLength) {
  101. const val = getDictionaryReversed(code);
  102. appendReversed(result, val);
  103. addToDictionary(oldCode, val[val.length - 1]);
  104. oldCode = code;
  105. }
  106. else {
  107. const oldVal = getDictionaryReversed(oldCode);
  108. if (!oldVal) {
  109. throw new Error(`Bogus entry. Not in dictionary, ${oldCode} / ${dictionaryLength}, position: ${position}`);
  110. }
  111. appendReversed(result, oldVal);
  112. result.push(oldVal[oldVal.length - 1]);
  113. addToDictionary(oldCode, oldVal[oldVal.length - 1]);
  114. oldCode = code;
  115. }
  116. if (dictionaryLength + 1 >= (2 ** byteLength)) {
  117. if (byteLength === MAX_BYTELENGTH) {
  118. oldCode = undefined;
  119. }
  120. else {
  121. byteLength++;
  122. }
  123. }
  124. code = getNext(array);
  125. }
  126. return new Uint8Array(result);
  127. }
  128. class LZWDecoder extends basedecoder_js_1.default {
  129. decodeBlock(buffer) {
  130. return decompress(buffer, false).buffer;
  131. }
  132. }
  133. exports.default = LZWDecoder;
  134. //# sourceMappingURL=lzw.js.map