| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- /* Copyright 2012 Mozilla Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- // Table C-2
- const QeTable = [
- { qe: 0x5601, nmps: 1, nlps: 1, switchFlag: 1 },
- { qe: 0x3401, nmps: 2, nlps: 6, switchFlag: 0 },
- { qe: 0x1801, nmps: 3, nlps: 9, switchFlag: 0 },
- { qe: 0x0ac1, nmps: 4, nlps: 12, switchFlag: 0 },
- { qe: 0x0521, nmps: 5, nlps: 29, switchFlag: 0 },
- { qe: 0x0221, nmps: 38, nlps: 33, switchFlag: 0 },
- { qe: 0x5601, nmps: 7, nlps: 6, switchFlag: 1 },
- { qe: 0x5401, nmps: 8, nlps: 14, switchFlag: 0 },
- { qe: 0x4801, nmps: 9, nlps: 14, switchFlag: 0 },
- { qe: 0x3801, nmps: 10, nlps: 14, switchFlag: 0 },
- { qe: 0x3001, nmps: 11, nlps: 17, switchFlag: 0 },
- { qe: 0x2401, nmps: 12, nlps: 18, switchFlag: 0 },
- { qe: 0x1c01, nmps: 13, nlps: 20, switchFlag: 0 },
- { qe: 0x1601, nmps: 29, nlps: 21, switchFlag: 0 },
- { qe: 0x5601, nmps: 15, nlps: 14, switchFlag: 1 },
- { qe: 0x5401, nmps: 16, nlps: 14, switchFlag: 0 },
- { qe: 0x5101, nmps: 17, nlps: 15, switchFlag: 0 },
- { qe: 0x4801, nmps: 18, nlps: 16, switchFlag: 0 },
- { qe: 0x3801, nmps: 19, nlps: 17, switchFlag: 0 },
- { qe: 0x3401, nmps: 20, nlps: 18, switchFlag: 0 },
- { qe: 0x3001, nmps: 21, nlps: 19, switchFlag: 0 },
- { qe: 0x2801, nmps: 22, nlps: 19, switchFlag: 0 },
- { qe: 0x2401, nmps: 23, nlps: 20, switchFlag: 0 },
- { qe: 0x2201, nmps: 24, nlps: 21, switchFlag: 0 },
- { qe: 0x1c01, nmps: 25, nlps: 22, switchFlag: 0 },
- { qe: 0x1801, nmps: 26, nlps: 23, switchFlag: 0 },
- { qe: 0x1601, nmps: 27, nlps: 24, switchFlag: 0 },
- { qe: 0x1401, nmps: 28, nlps: 25, switchFlag: 0 },
- { qe: 0x1201, nmps: 29, nlps: 26, switchFlag: 0 },
- { qe: 0x1101, nmps: 30, nlps: 27, switchFlag: 0 },
- { qe: 0x0ac1, nmps: 31, nlps: 28, switchFlag: 0 },
- { qe: 0x09c1, nmps: 32, nlps: 29, switchFlag: 0 },
- { qe: 0x08a1, nmps: 33, nlps: 30, switchFlag: 0 },
- { qe: 0x0521, nmps: 34, nlps: 31, switchFlag: 0 },
- { qe: 0x0441, nmps: 35, nlps: 32, switchFlag: 0 },
- { qe: 0x02a1, nmps: 36, nlps: 33, switchFlag: 0 },
- { qe: 0x0221, nmps: 37, nlps: 34, switchFlag: 0 },
- { qe: 0x0141, nmps: 38, nlps: 35, switchFlag: 0 },
- { qe: 0x0111, nmps: 39, nlps: 36, switchFlag: 0 },
- { qe: 0x0085, nmps: 40, nlps: 37, switchFlag: 0 },
- { qe: 0x0049, nmps: 41, nlps: 38, switchFlag: 0 },
- { qe: 0x0025, nmps: 42, nlps: 39, switchFlag: 0 },
- { qe: 0x0015, nmps: 43, nlps: 40, switchFlag: 0 },
- { qe: 0x0009, nmps: 44, nlps: 41, switchFlag: 0 },
- { qe: 0x0005, nmps: 45, nlps: 42, switchFlag: 0 },
- { qe: 0x0001, nmps: 45, nlps: 43, switchFlag: 0 },
- { qe: 0x5601, nmps: 46, nlps: 46, switchFlag: 0 },
- ];
- /**
- * This class implements the QM Coder decoding as defined in
- * JPEG 2000 Part I Final Committee Draft Version 1.0
- * Annex C.3 Arithmetic decoding procedure
- * available at http://www.jpeg.org/public/fcd15444-1.pdf
- *
- * The arithmetic decoder is used in conjunction with context models to decode
- * JPEG2000 and JBIG2 streams.
- */
- class ArithmeticDecoder {
- // C.3.5 Initialisation of the decoder (INITDEC)
- constructor(data, start, end) {
- this.data = data;
- this.bp = start;
- this.dataEnd = end;
- this.chigh = data[start];
- this.clow = 0;
- this.byteIn();
- this.chigh = ((this.chigh << 7) & 0xffff) | ((this.clow >> 9) & 0x7f);
- this.clow = (this.clow << 7) & 0xffff;
- this.ct -= 7;
- this.a = 0x8000;
- }
- // C.3.4 Compressed data input (BYTEIN)
- byteIn() {
- const data = this.data;
- let bp = this.bp;
- if (data[bp] === 0xff) {
- if (data[bp + 1] > 0x8f) {
- this.clow += 0xff00;
- this.ct = 8;
- } else {
- bp++;
- this.clow += data[bp] << 9;
- this.ct = 7;
- this.bp = bp;
- }
- } else {
- bp++;
- this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xff00;
- this.ct = 8;
- this.bp = bp;
- }
- if (this.clow > 0xffff) {
- this.chigh += this.clow >> 16;
- this.clow &= 0xffff;
- }
- }
- // C.3.2 Decoding a decision (DECODE)
- readBit(contexts, pos) {
- // Contexts are packed into 1 byte:
- // highest 7 bits carry cx.index, lowest bit carries cx.mps
- let cx_index = contexts[pos] >> 1,
- cx_mps = contexts[pos] & 1;
- const qeTableIcx = QeTable[cx_index];
- const qeIcx = qeTableIcx.qe;
- let d;
- let a = this.a - qeIcx;
- if (this.chigh < qeIcx) {
- // exchangeLps
- if (a < qeIcx) {
- a = qeIcx;
- d = cx_mps;
- cx_index = qeTableIcx.nmps;
- } else {
- a = qeIcx;
- d = 1 ^ cx_mps;
- if (qeTableIcx.switchFlag === 1) {
- cx_mps = d;
- }
- cx_index = qeTableIcx.nlps;
- }
- } else {
- this.chigh -= qeIcx;
- if ((a & 0x8000) !== 0) {
- this.a = a;
- return cx_mps;
- }
- // exchangeMps
- if (a < qeIcx) {
- d = 1 ^ cx_mps;
- if (qeTableIcx.switchFlag === 1) {
- cx_mps = d;
- }
- cx_index = qeTableIcx.nlps;
- } else {
- d = cx_mps;
- cx_index = qeTableIcx.nmps;
- }
- }
- // C.3.3 renormD;
- do {
- if (this.ct === 0) {
- this.byteIn();
- }
- a <<= 1;
- this.chigh = ((this.chigh << 1) & 0xffff) | ((this.clow >> 15) & 1);
- this.clow = (this.clow << 1) & 0xffff;
- this.ct--;
- } while ((a & 0x8000) === 0);
- this.a = a;
- contexts[pos] = (cx_index << 1) | cx_mps;
- return d;
- }
- }
- export { ArithmeticDecoder };
|