UNPKG

@abasb75/jpeg-lossless-decoder

Version:
1,014 lines (1,013 loc) 37.6 kB
import { DataStream } from './data-stream'; import { FrameHeader } from './frame-header'; import { HuffmanTable } from './huffman-table'; import { QuantizationTable } from './quantization-table'; import { ScanHeader } from './scan-header'; import { createArray } from './utils'; var littleEndian = (function () { var buffer = new ArrayBuffer(2); new DataView(buffer).setInt16(0, 256, true /* littleEndian */); // Int16Array uses the platform's endianness. return new Int16Array(buffer)[0] === 256; })(); var Decoder = /** @class */ (function () { /** * The Decoder constructor. * @property {number} numBytes - number of bytes per component * @type {Function} */ function Decoder(buffer, numBytes) { Object.defineProperty(this, "buffer", { enumerable: true, configurable: true, writable: true, value: null }); Object.defineProperty(this, "stream", { enumerable: true, configurable: true, writable: true, value: null }); Object.defineProperty(this, "frame", { enumerable: true, configurable: true, writable: true, value: new FrameHeader() }); Object.defineProperty(this, "huffTable", { enumerable: true, configurable: true, writable: true, value: new HuffmanTable() }); Object.defineProperty(this, "quantTable", { enumerable: true, configurable: true, writable: true, value: new QuantizationTable() }); Object.defineProperty(this, "scan", { enumerable: true, configurable: true, writable: true, value: new ScanHeader() }); Object.defineProperty(this, "DU", { enumerable: true, configurable: true, writable: true, value: createArray(10, 4, 64) }); // at most 10 data units in a MCU, at most 4 data units in one component Object.defineProperty(this, "HuffTab", { enumerable: true, configurable: true, writable: true, value: createArray(4, 2, 50 * 256) }); Object.defineProperty(this, "IDCT_Source", { enumerable: true, configurable: true, writable: true, value: [] }); Object.defineProperty(this, "nBlock", { enumerable: true, configurable: true, writable: true, value: [] }); // number of blocks in the i-th Comp in a scan Object.defineProperty(this, "acTab", { enumerable: true, configurable: true, writable: true, value: createArray(10, 1) }); // ac HuffTab for the i-th Comp in a scan Object.defineProperty(this, "dcTab", { enumerable: true, configurable: true, writable: true, value: createArray(10, 1) }); // dc HuffTab for the i-th Comp in a scan Object.defineProperty(this, "qTab", { enumerable: true, configurable: true, writable: true, value: createArray(10, 1) }); // quantization table for the i-th Comp in a scan Object.defineProperty(this, "marker", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "markerIndex", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "numComp", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "restartInterval", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "selection", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "xDim", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "yDim", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "xLoc", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "yLoc", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "outputData", { enumerable: true, configurable: true, writable: true, value: null }); Object.defineProperty(this, "restarting", { enumerable: true, configurable: true, writable: true, value: false }); Object.defineProperty(this, "mask", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "numBytes", { enumerable: true, configurable: true, writable: true, value: 0 }); Object.defineProperty(this, "precision", { enumerable: true, configurable: true, writable: true, value: undefined }); Object.defineProperty(this, "components", { enumerable: true, configurable: true, writable: true, value: [] }); Object.defineProperty(this, "getter", { enumerable: true, configurable: true, writable: true, value: null }); Object.defineProperty(this, "setter", { enumerable: true, configurable: true, writable: true, value: null }); Object.defineProperty(this, "output", { enumerable: true, configurable: true, writable: true, value: null }); Object.defineProperty(this, "selector", { enumerable: true, configurable: true, writable: true, value: null }); this.buffer = buffer !== null && buffer !== void 0 ? buffer : null; this.numBytes = numBytes !== null && numBytes !== void 0 ? numBytes : 0; } /** * Returns decompressed data. */ Object.defineProperty(Decoder.prototype, "decompress", { enumerable: false, configurable: true, writable: true, value: function (buffer, offset, length) { var result = this.decode(buffer, offset, length); return result.buffer; } }); Object.defineProperty(Decoder.prototype, "decode", { enumerable: false, configurable: true, writable: true, value: function (buffer, offset, length, numBytes) { var _a, _b; var scanNum = 0; var pred = []; var i; var compN; var temp = []; var index = []; var mcuNum; if (buffer) { this.buffer = buffer; } if (numBytes !== undefined) { this.numBytes = numBytes; } this.stream = new DataStream(this.buffer, offset, length); this.buffer = null; this.xLoc = 0; this.yLoc = 0; var current = this.stream.get16(); if (current !== 0xffd8) { // SOI throw new Error('Not a JPEG file'); } current = this.stream.get16(); while (current >> 4 !== 0x0ffc || current === 0xffc4) { // SOF 0~15 switch (current) { case 0xffc4: // DHT this.huffTable.read(this.stream, this.HuffTab); break; case 0xffcc: // DAC throw new Error("Program doesn't support arithmetic coding. (format throw new IOException)"); case 0xffdb: this.quantTable.read(this.stream, Decoder.TABLE); break; case 0xffdd: this.restartInterval = (_a = this.readNumber()) !== null && _a !== void 0 ? _a : 0; break; case 0xffe0: case 0xffe1: case 0xffe2: case 0xffe3: case 0xffe4: case 0xffe5: case 0xffe6: case 0xffe7: case 0xffe8: case 0xffe9: case 0xffea: case 0xffeb: case 0xffec: case 0xffed: case 0xffee: case 0xffef: this.readApp(); break; case 0xfffe: this.readComment(); break; default: if (current >> 8 !== 0xff) { throw new Error('ERROR: format throw new IOException! (decode)'); } } current = this.stream.get16(); } if (current < 0xffc0 || current > 0xffc7) { throw new Error('ERROR: could not handle arithmetic code!'); } this.frame.read(this.stream); current = this.stream.get16(); do { while (current !== 0x0ffda) { // SOS switch (current) { case 0xffc4: // DHT this.huffTable.read(this.stream, this.HuffTab); break; case 0xffcc: // DAC throw new Error("Program doesn't support arithmetic coding. (format throw new IOException)"); case 0xffdb: this.quantTable.read(this.stream, Decoder.TABLE); break; case 0xffdd: this.restartInterval = (_b = this.readNumber()) !== null && _b !== void 0 ? _b : 0; break; case 0xffe0: case 0xffe1: case 0xffe2: case 0xffe3: case 0xffe4: case 0xffe5: case 0xffe6: case 0xffe7: case 0xffe8: case 0xffe9: case 0xffea: case 0xffeb: case 0xffec: case 0xffed: case 0xffee: case 0xffef: this.readApp(); break; case 0xfffe: this.readComment(); break; default: if (current >> 8 !== 0xff) { throw new Error('ERROR: format throw new IOException! (Parser.decode)'); } } current = this.stream.get16(); } this.precision = this.frame.precision; this.components = this.frame.components; if (!this.numBytes) { this.numBytes = Math.round(Math.ceil(this.precision / 8)); } if (this.numBytes === 1) { this.mask = 0xff; } else { this.mask = 0xffff; } this.scan.read(this.stream); this.numComp = this.scan.numComp; this.selection = this.scan.selection; if (this.numBytes === 1) { if (this.numComp === 3) { this.getter = this.getValueRGB; this.setter = this.setValueRGB; this.output = this.outputRGB; } else { this.getter = this.getValue8; this.setter = this.setValue8; this.output = this.outputSingle; } } else { this.getter = this.getValue8; this.setter = this.setValue8; this.output = this.outputSingle; } switch (this.selection) { case 2: this.selector = this.select2; break; case 3: this.selector = this.select3; break; case 4: this.selector = this.select4; break; case 5: this.selector = this.select5; break; case 6: this.selector = this.select6; break; case 7: this.selector = this.select7; break; default: this.selector = this.select1; break; } // this.scanComps = this.scan.components // this.quantTables = this.quantTable.quantTables for (i = 0; i < this.numComp; i += 1) { compN = this.scan.components[i].scanCompSel; this.qTab[i] = this.quantTable.quantTables[this.components[compN].quantTableSel]; this.nBlock[i] = this.components[compN].vSamp * this.components[compN].hSamp; this.dcTab[i] = this.HuffTab[this.scan.components[i].dcTabSel][0]; this.acTab[i] = this.HuffTab[this.scan.components[i].acTabSel][1]; } this.xDim = this.frame.dimX; this.yDim = this.frame.dimY; if (this.numBytes === 1) { this.outputData = new Uint8Array(new ArrayBuffer(this.xDim * this.yDim * this.numBytes * this.numComp)); } else { this.outputData = new Uint16Array(new ArrayBuffer(this.xDim * this.yDim * this.numBytes * this.numComp)); } scanNum += 1; while (true) { // Decode one scan temp[0] = 0; index[0] = 0; for (i = 0; i < 10; i += 1) { pred[i] = 1 << (this.precision - 1); } if (this.restartInterval === 0) { current = this.decodeUnit(pred, temp, index); while (current === 0 && this.xLoc < this.xDim && this.yLoc < this.yDim) { this.output(pred); current = this.decodeUnit(pred, temp, index); } break; // current=MARKER } for (mcuNum = 0; mcuNum < this.restartInterval; mcuNum += 1) { this.restarting = mcuNum === 0; current = this.decodeUnit(pred, temp, index); this.output(pred); if (current !== 0) { break; } } if (current === 0) { if (this.markerIndex !== 0) { current = 0xff00 | this.marker; this.markerIndex = 0; } else { current = this.stream.get16(); } } if (!(current >= Decoder.RESTART_MARKER_BEGIN && current <= Decoder.RESTART_MARKER_END)) { break; // current=MARKER } } if (current === 0xffdc && scanNum === 1) { // DNL this.readNumber(); current = this.stream.get16(); } } while (current !== 0xffd9 && this.xLoc < this.xDim && this.yLoc < this.yDim && scanNum === 0); return this.outputData; } }); Object.defineProperty(Decoder.prototype, "decodeUnit", { enumerable: false, configurable: true, writable: true, value: function (prev, temp, index) { if (this.numComp === 1) { return this.decodeSingle(prev, temp, index); } else if (this.numComp === 3) { return this.decodeRGB(prev, temp, index); } else { return -1; } } }); Object.defineProperty(Decoder.prototype, "select1", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { return this.getPreviousX(compOffset); } }); Object.defineProperty(Decoder.prototype, "select2", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { return this.getPreviousY(compOffset); } }); Object.defineProperty(Decoder.prototype, "select3", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { return this.getPreviousXY(compOffset); } }); Object.defineProperty(Decoder.prototype, "select4", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { return this.getPreviousX(compOffset) + this.getPreviousY(compOffset) - this.getPreviousXY(compOffset); } }); Object.defineProperty(Decoder.prototype, "select5", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { return this.getPreviousX(compOffset) + ((this.getPreviousY(compOffset) - this.getPreviousXY(compOffset)) >> 1); } }); Object.defineProperty(Decoder.prototype, "select6", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { return this.getPreviousY(compOffset) + ((this.getPreviousX(compOffset) - this.getPreviousXY(compOffset)) >> 1); } }); Object.defineProperty(Decoder.prototype, "select7", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { return (this.getPreviousX(compOffset) + this.getPreviousY(compOffset)) / 2; } }); Object.defineProperty(Decoder.prototype, "decodeRGB", { enumerable: false, configurable: true, writable: true, value: function (prev, temp, index) { if (this.selector === null) throw new Error("decode hasn't run yet"); var actab, dctab, qtab, ctrC, i, k, j; prev[0] = this.selector(0); prev[1] = this.selector(1); prev[2] = this.selector(2); for (ctrC = 0; ctrC < this.numComp; ctrC += 1) { qtab = this.qTab[ctrC]; actab = this.acTab[ctrC]; dctab = this.dcTab[ctrC]; for (i = 0; i < this.nBlock[ctrC]; i += 1) { for (k = 0; k < this.IDCT_Source.length; k += 1) { this.IDCT_Source[k] = 0; } var value = this.getHuffmanValue(dctab, temp, index); if (value >= 0xff00) { return value; } prev[ctrC] = this.IDCT_Source[0] = prev[ctrC] + this.getn(index, value, temp, index); this.IDCT_Source[0] *= qtab[0]; for (j = 1; j < 64; j += 1) { value = this.getHuffmanValue(actab, temp, index); if (value >= 0xff00) { return value; } j += value >> 4; if ((value & 0x0f) === 0) { if (value >> 4 === 0) { break; } } else { this.IDCT_Source[Decoder.IDCT_P[j]] = this.getn(index, value & 0x0f, temp, index) * qtab[j]; } } } } return 0; } }); Object.defineProperty(Decoder.prototype, "decodeSingle", { enumerable: false, configurable: true, writable: true, value: function (prev, temp, index) { if (this.selector === null) throw new Error("decode hasn't run yet"); var value, i, n, nRestart; if (this.restarting) { this.restarting = false; prev[0] = 1 << (this.frame.precision - 1); } else { prev[0] = this.selector(); } for (i = 0; i < this.nBlock[0]; i += 1) { value = this.getHuffmanValue(this.dcTab[0], temp, index); if (value >= 0xff00) { return value; } n = this.getn(prev, value, temp, index); nRestart = n >> 8; if (nRestart >= Decoder.RESTART_MARKER_BEGIN && nRestart <= Decoder.RESTART_MARKER_END) { return nRestart; } prev[0] += n; } return 0; } }); // Huffman table for fast search: (HuffTab) 8-bit Look up table 2-layer search architecture, 1st-layer represent 256 node (8 bits) if codeword-length > 8 // bits, then the entry of 1st-layer = (# of 2nd-layer table) | MSB and it is stored in the 2nd-layer Size of tables in each layer are 256. // HuffTab[*][*][0-256] is always the only 1st-layer table. // // An entry can be: (1) (# of 2nd-layer table) | MSB , for code length > 8 in 1st-layer (2) (Code length) << 8 | HuffVal // // HuffmanValue(table HuffTab[x][y] (ex) HuffmanValue(HuffTab[1][0],...) // ): // return: Huffman Value of table // 0xFF?? if it receives a MARKER // Parameter: table HuffTab[x][y] (ex) HuffmanValue(HuffTab[1][0],...) // temp temp storage for remainded bits // index index to bit of temp // in FILE pointer // Effect: // temp store new remainded bits // index change to new index // in change to new position // NOTE: // Initial by temp=0; index=0; // NOTE: (explain temp and index) // temp: is always in the form at calling time or returning time // | byte 4 | byte 3 | byte 2 | byte 1 | // | 0 | 0 | 00000000 | 00000??? | if not a MARKER // ^index=3 (from 0 to 15) // 321 // NOTE (marker and marker_index): // If get a MARKER from 'in', marker=the low-byte of the MARKER // and marker_index=9 // If marker_index=9 then index is always > 8, or HuffmanValue() // will not be called Object.defineProperty(Decoder.prototype, "getHuffmanValue", { enumerable: false, configurable: true, writable: true, value: function (table, temp, index) { var code, input; var mask = 0xffff; if (!this.stream) throw new Error('stream not initialized'); if (index[0] < 8) { temp[0] <<= 8; input = this.stream.get8(); if (input === 0xff) { this.marker = this.stream.get8(); if (this.marker !== 0) { this.markerIndex = 9; } } temp[0] |= input; } else { index[0] -= 8; } code = table[temp[0] >> index[0]]; if ((code & Decoder.MSB) !== 0) { if (this.markerIndex !== 0) { this.markerIndex = 0; return 0xff00 | this.marker; } temp[0] &= mask >> (16 - index[0]); temp[0] <<= 8; input = this.stream.get8(); if (input === 0xff) { this.marker = this.stream.get8(); if (this.marker !== 0) { this.markerIndex = 9; } } temp[0] |= input; code = table[(code & 0xff) * 256 + (temp[0] >> index[0])]; index[0] += 8; } index[0] += 8 - (code >> 8); if (index[0] < 0) { throw new Error('index=' + index[0] + ' temp=' + temp[0] + ' code=' + code + ' in HuffmanValue()'); } if (index[0] < this.markerIndex) { this.markerIndex = 0; return 0xff00 | this.marker; } temp[0] &= mask >> (16 - index[0]); return code & 0xff; } }); Object.defineProperty(Decoder.prototype, "getn", { enumerable: false, configurable: true, writable: true, value: function (PRED, n, temp, index) { var result, input; var one = 1; var n_one = -1; var mask = 0xffff; if (this.stream === null) throw new Error('stream not initialized'); if (n === 0) { return 0; } if (n === 16) { if (PRED[0] >= 0) { return -32768; } else { return 32768; } } index[0] -= n; if (index[0] >= 0) { if (index[0] < this.markerIndex && !this.isLastPixel()) { // this was corrupting the last pixel in some cases this.markerIndex = 0; return (0xff00 | this.marker) << 8; } result = temp[0] >> index[0]; temp[0] &= mask >> (16 - index[0]); } else { temp[0] <<= 8; input = this.stream.get8(); if (input === 0xff) { this.marker = this.stream.get8(); if (this.marker !== 0) { this.markerIndex = 9; } } temp[0] |= input; index[0] += 8; if (index[0] < 0) { if (this.markerIndex !== 0) { this.markerIndex = 0; return (0xff00 | this.marker) << 8; } temp[0] <<= 8; input = this.stream.get8(); if (input === 0xff) { this.marker = this.stream.get8(); if (this.marker !== 0) { this.markerIndex = 9; } } temp[0] |= input; index[0] += 8; } if (index[0] < 0) { throw new Error('index=' + index[0] + ' in getn()'); } if (index[0] < this.markerIndex) { this.markerIndex = 0; return (0xff00 | this.marker) << 8; } result = temp[0] >> index[0]; temp[0] &= mask >> (16 - index[0]); } if (result < one << (n - 1)) { result += (n_one << n) + 1; } return result; } }); Object.defineProperty(Decoder.prototype, "getPreviousX", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { if (compOffset === void 0) { compOffset = 0; } if (this.getter === null) throw new Error("decode hasn't run yet"); if (this.xLoc > 0) { return this.getter(this.yLoc * this.xDim + this.xLoc - 1, compOffset); } else if (this.yLoc > 0) { return this.getPreviousY(compOffset); } else { return 1 << (this.frame.precision - 1); } } }); Object.defineProperty(Decoder.prototype, "getPreviousXY", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { if (compOffset === void 0) { compOffset = 0; } if (this.getter === null) throw new Error("decode hasn't run yet"); if (this.xLoc > 0 && this.yLoc > 0) { return this.getter((this.yLoc - 1) * this.xDim + this.xLoc - 1, compOffset); } else { return this.getPreviousY(compOffset); } } }); Object.defineProperty(Decoder.prototype, "getPreviousY", { enumerable: false, configurable: true, writable: true, value: function (compOffset) { if (compOffset === void 0) { compOffset = 0; } if (this.getter === null) throw new Error("decode hasn't run yet"); if (this.yLoc > 0) { return this.getter((this.yLoc - 1) * this.xDim + this.xLoc, compOffset); } else { return this.getPreviousX(compOffset); } } }); Object.defineProperty(Decoder.prototype, "isLastPixel", { enumerable: false, configurable: true, writable: true, value: function () { return this.xLoc === this.xDim - 1 && this.yLoc === this.yDim - 1; } }); Object.defineProperty(Decoder.prototype, "outputSingle", { enumerable: false, configurable: true, writable: true, value: function (PRED) { if (this.setter === null) throw new Error("decode hasn't run yet"); if (this.xLoc < this.xDim && this.yLoc < this.yDim) { this.setter(this.yLoc * this.xDim + this.xLoc, this.mask & PRED[0]); this.xLoc += 1; if (this.xLoc >= this.xDim) { this.yLoc += 1; this.xLoc = 0; } } } }); Object.defineProperty(Decoder.prototype, "outputRGB", { enumerable: false, configurable: true, writable: true, value: function (PRED) { if (this.setter === null) throw new Error("decode hasn't run yet"); var offset = this.yLoc * this.xDim + this.xLoc; if (this.xLoc < this.xDim && this.yLoc < this.yDim) { this.setter(offset, PRED[0], 0); this.setter(offset, PRED[1], 1); this.setter(offset, PRED[2], 2); this.xLoc += 1; if (this.xLoc >= this.xDim) { this.yLoc += 1; this.xLoc = 0; } } } }); Object.defineProperty(Decoder.prototype, "setValue8", { enumerable: false, configurable: true, writable: true, value: function (index, val) { if (!this.outputData) throw new Error('output data not ready'); if (littleEndian) { this.outputData[index] = val; } else { this.outputData[index] = ((val & 0xff) << 8) | ((val >> 8) & 0xff); } } }); Object.defineProperty(Decoder.prototype, "getValue8", { enumerable: false, configurable: true, writable: true, value: function (index) { if (this.outputData === null) throw new Error('output data not ready'); if (littleEndian) { return this.outputData[index]; // mask should not be necessary because outputData is either Int8Array or Int16Array } else { var val = this.outputData[index]; return ((val & 0xff) << 8) | ((val >> 8) & 0xff); } } }); Object.defineProperty(Decoder.prototype, "setValueRGB", { enumerable: false, configurable: true, writable: true, value: function (index, val, compOffset) { if (compOffset === void 0) { compOffset = 0; } if (this.outputData === null) return; this.outputData[index * 3 + compOffset] = val; } }); Object.defineProperty(Decoder.prototype, "getValueRGB", { enumerable: false, configurable: true, writable: true, value: function (index, compOffset) { if (this.outputData === null) throw new Error('output data not ready'); return this.outputData[index * 3 + compOffset]; } }); Object.defineProperty(Decoder.prototype, "readApp", { enumerable: false, configurable: true, writable: true, value: function () { if (this.stream === null) return null; var count = 0; var length = this.stream.get16(); count += 2; while (count < length) { this.stream.get8(); count += 1; } return length; } }); Object.defineProperty(Decoder.prototype, "readComment", { enumerable: false, configurable: true, writable: true, value: function () { if (this.stream === null) return null; var sb = ''; var count = 0; var length = this.stream.get16(); count += 2; while (count < length) { sb += this.stream.get8(); count += 1; } return sb; } }); Object.defineProperty(Decoder.prototype, "readNumber", { enumerable: false, configurable: true, writable: true, value: function () { if (this.stream === null) return null; var Ld = this.stream.get16(); if (Ld !== 4) { throw new Error('ERROR: Define number format throw new IOException [Ld!=4]'); } return this.stream.get16(); } }); Object.defineProperty(Decoder, "IDCT_P", { enumerable: true, configurable: true, writable: true, value: [ 0, 5, 40, 16, 45, 2, 7, 42, 21, 56, 8, 61, 18, 47, 1, 4, 41, 23, 58, 13, 32, 24, 37, 10, 63, 17, 44, 3, 6, 43, 20, 57, 15, 34, 29, 48, 53, 26, 39, 9, 60, 19, 46, 22, 59, 12, 33, 31, 50, 55, 25, 36, 11, 62, 14, 35, 28, 49, 52, 27, 38, 30, 51, 54 ] }); Object.defineProperty(Decoder, "TABLE", { enumerable: true, configurable: true, writable: true, value: [ 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63 ] }); Object.defineProperty(Decoder, "MAX_HUFFMAN_SUBTREE", { enumerable: true, configurable: true, writable: true, value: 50 }); Object.defineProperty(Decoder, "MSB", { enumerable: true, configurable: true, writable: true, value: 0x80000000 }); Object.defineProperty(Decoder, "RESTART_MARKER_BEGIN", { enumerable: true, configurable: true, writable: true, value: 0xffd0 }); Object.defineProperty(Decoder, "RESTART_MARKER_END", { enumerable: true, configurable: true, writable: true, value: 0xffd7 }); return Decoder; }()); export { Decoder };