UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

214 lines (190 loc) • 6.48 kB
// IDCT constants (20.12 fixed point format) const dctCos1 = 4017; // cos(pi/16) const dctSin1 = 799; // sin(pi/16) const dctCos3 = 3406; // cos(3*pi/16) const dctSin3 = 2276; // sin(3*pi/16) const dctCos6 = 1567; // cos(6*pi/16) const dctSin6 = 3784; // sin(6*pi/16) const dctSqrt2 = 5793; // sqrt(2) const dctSqrt1d2 = 2896; // sqrt(2) / 2 /** * Used internally for transformation * @type {Int32Array} */ const p = new Int32Array(64); /** * Decode 8x8 block quantized DCT coefficients and inverse DCT transform. * This is a fixed-point implementation of the IDCT algorithm. * * This IDCT algorithm is taken from: * Y. A. Reznik, A. T. Hinds, L. Yu, Z. Ni, and C-X. Zhang, * "Efficient fixed-point approximations of the 8x8 inverse discrete * cosine transform" (invited paper), Proc. SPIE Vol. 6696, Sep. 24, 2007. * * which is based on: * Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz, * "Practical Fast 1-D DCT Algorithms with 11 Multiplications", * IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989, * 988-991. * * The stage numbers mentioned in the comments refer to Figure 1 in the Loeffler paper. * * @param {Int32Array} qt quantization table * @param {Int32Array} zz zigzag-ordered coefficients * @param {Uint8Array|Uint8ClampedArray} dataOut */ export function idct8x8_fixed( qt, zz, dataOut, ) { // TODO check https://github.com/ONLYOFFICE/core/blob/f6c835668482d70e59202394434314c8863fc1cf/PdfFile/lib/xpdf/Stream.cc#L3582 let v0, v1, v2, v3, v4, v5, v6, v7, t; let i; // dequant for (i = 0; i < 64; i++) { p[i] = zz[i] * qt[i]; } // inverse DCT on rows for (i = 0; i < 8; ++i) { const row = 8 * i; // check for all-zero AC coefficients if (p[1 + row] === 0 && p[2 + row] === 0 && p[3 + row] === 0 && p[4 + row] === 0 && p[5 + row] === 0 && p[6 + row] === 0 && p[7 + row] === 0 ) { t = (dctSqrt2 * p[0 + row] + 512) >> 10; p[0 + row] = t; p[1 + row] = t; p[2 + row] = t; p[3 + row] = t; p[4 + row] = t; p[5 + row] = t; p[6 + row] = t; p[7 + row] = t; continue; } // stage 4 v0 = (dctSqrt2 * p[0 + row] + 128) >> 8; v1 = (dctSqrt2 * p[4 + row] + 128) >> 8; v2 = p[2 + row]; v3 = p[6 + row]; v4 = (dctSqrt1d2 * (p[1 + row] - p[7 + row]) + 128) >> 8; v7 = (dctSqrt1d2 * (p[1 + row] + p[7 + row]) + 128) >> 8; v5 = p[3 + row] << 4; v6 = p[5 + row] << 4; // stage 3 t = (v0 - v1 + 1) >> 1; v0 = (v0 + v1 + 1) >> 1; v1 = t; t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; v3 = t; t = (v4 - v6 + 1) >> 1; v4 = (v4 + v6 + 1) >> 1; v6 = t; t = (v7 + v5 + 1) >> 1; v5 = (v7 - v5 + 1) >> 1; v7 = t; // stage 2 t = (v0 - v3 + 1) >> 1; v0 = (v0 + v3 + 1) >> 1; v3 = t; t = (v1 - v2 + 1) >> 1; v1 = (v1 + v2 + 1) >> 1; v2 = t; t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; v7 = t; t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; v6 = t; // stage 1 p[0 + row] = v0 + v7; p[7 + row] = v0 - v7; p[1 + row] = v1 + v6; p[6 + row] = v1 - v6; p[2 + row] = v2 + v5; p[5 + row] = v2 - v5; p[3 + row] = v3 + v4; p[4 + row] = v3 - v4; } // inverse DCT on columns for (i = 0; i < 8; ++i) { const col = i; // check for all-zero AC coefficients if (p[1 * 8 + col] === 0 && p[2 * 8 + col] === 0 && p[3 * 8 + col] === 0 && p[4 * 8 + col] === 0 && p[5 * 8 + col] === 0 && p[6 * 8 + col] === 0 && p[7 * 8 + col] === 0 ) { t = (dctSqrt2 * p[i + 0] + 8192) >> 14; p[0 * 8 + col] = t; p[1 * 8 + col] = t; p[2 * 8 + col] = t; p[3 * 8 + col] = t; p[4 * 8 + col] = t; p[5 * 8 + col] = t; p[6 * 8 + col] = t; p[7 * 8 + col] = t; continue; } // stage 4 v0 = (dctSqrt2 * p[0 * 8 + col] + 2048) >> 12; v1 = (dctSqrt2 * p[4 * 8 + col] + 2048) >> 12; v2 = p[2 * 8 + col]; v3 = p[6 * 8 + col]; v4 = (dctSqrt1d2 * (p[1 * 8 + col] - p[7 * 8 + col]) + 2048) >> 12; v7 = (dctSqrt1d2 * (p[1 * 8 + col] + p[7 * 8 + col]) + 2048) >> 12; v5 = p[3 * 8 + col]; v6 = p[5 * 8 + col]; // stage 3 t = (v0 - v1 + 1) >> 1; v0 = (v0 + v1 + 1) >> 1; v1 = t; t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; v3 = t; t = (v4 - v6 + 1) >> 1; v4 = (v4 + v6 + 1) >> 1; v6 = t; t = (v7 + v5 + 1) >> 1; v5 = (v7 - v5 + 1) >> 1; v7 = t; // stage 2 t = (v0 - v3 + 1) >> 1; v0 = (v0 + v3 + 1) >> 1; v3 = t; t = (v1 - v2 + 1) >> 1; v1 = (v1 + v2 + 1) >> 1; v2 = t; t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; v7 = t; t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; v6 = t; // stage 1 p[0 * 8 + col] = v0 + v7; p[7 * 8 + col] = v0 - v7; p[1 * 8 + col] = v1 + v6; p[6 * 8 + col] = v1 - v6; p[2 * 8 + col] = v2 + v5; p[5 * 8 + col] = v2 - v5; p[3 * 8 + col] = v3 + v4; p[4 * 8 + col] = v3 - v4; } // convert to 8-bit integers for (i = 0; i < 64; ++i) { const q = p[i]; // clip to 8-bit range dataOut[i] = (q <= -2056) ? 0 : (q >= 2024) ? 255 : (q + 2056) >> 4; } }