Merge pull request #13338 from Snuffleupagus/images-class
Convert the `src/core/{jbig2, jpg, jpx}.js` files to use standard classes
This commit is contained in:
commit
5248d0a77d
File diff suppressed because it is too large
Load Diff
358
src/core/jpg.js
358
src/core/jpg.js
@ -12,7 +12,6 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
/* eslint-disable no-var */
|
|
||||||
|
|
||||||
import { assert, BaseException, warn } from "../shared/util.js";
|
import { assert, BaseException, warn } from "../shared/util.js";
|
||||||
import { readUint16 } from "./core_utils.js";
|
import { readUint16 } from "./core_utils.js";
|
||||||
@ -45,9 +44,8 @@ class EOIMarkerError extends BaseException {}
|
|||||||
* (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
|
* (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var JpegImage = (function JpegImageClosure() {
|
// prettier-ignore
|
||||||
// prettier-ignore
|
const dctZigZag = new Uint8Array([
|
||||||
var dctZigZag = new Uint8Array([
|
|
||||||
0,
|
0,
|
||||||
1, 8,
|
1, 8,
|
||||||
16, 9, 2,
|
16, 9, 2,
|
||||||
@ -65,32 +63,25 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
63
|
63
|
||||||
]);
|
]);
|
||||||
|
|
||||||
var dctCos1 = 4017; // cos(pi/16)
|
const dctCos1 = 4017; // cos(pi/16)
|
||||||
var dctSin1 = 799; // sin(pi/16)
|
const dctSin1 = 799; // sin(pi/16)
|
||||||
var dctCos3 = 3406; // cos(3*pi/16)
|
const dctCos3 = 3406; // cos(3*pi/16)
|
||||||
var dctSin3 = 2276; // sin(3*pi/16)
|
const dctSin3 = 2276; // sin(3*pi/16)
|
||||||
var dctCos6 = 1567; // cos(6*pi/16)
|
const dctCos6 = 1567; // cos(6*pi/16)
|
||||||
var dctSin6 = 3784; // sin(6*pi/16)
|
const dctSin6 = 3784; // sin(6*pi/16)
|
||||||
var dctSqrt2 = 5793; // sqrt(2)
|
const dctSqrt2 = 5793; // sqrt(2)
|
||||||
var dctSqrt1d2 = 2896; // sqrt(2) / 2
|
const dctSqrt1d2 = 2896; // sqrt(2) / 2
|
||||||
|
|
||||||
// eslint-disable-next-line no-shadow
|
function buildHuffmanTable(codeLengths, values) {
|
||||||
function JpegImage({ decodeTransform = null, colorTransform = -1 } = {}) {
|
let k = 0,
|
||||||
this._decodeTransform = decodeTransform;
|
|
||||||
this._colorTransform = colorTransform;
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildHuffmanTable(codeLengths, values) {
|
|
||||||
var k = 0,
|
|
||||||
code = [],
|
|
||||||
i,
|
i,
|
||||||
j,
|
j,
|
||||||
length = 16;
|
length = 16;
|
||||||
while (length > 0 && !codeLengths[length - 1]) {
|
while (length > 0 && !codeLengths[length - 1]) {
|
||||||
length--;
|
length--;
|
||||||
}
|
}
|
||||||
code.push({ children: [], index: 0 });
|
const code = [{ children: [], index: 0 }];
|
||||||
var p = code[0],
|
let p = code[0],
|
||||||
q;
|
q;
|
||||||
for (i = 0; i < length; i++) {
|
for (i = 0; i < length; i++) {
|
||||||
for (j = 0; j < codeLengths[i]; j++) {
|
for (j = 0; j < codeLengths[i]; j++) {
|
||||||
@ -116,13 +107,13 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return code[0].children;
|
return code[0].children;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBlockBufferOffset(component, row, col) {
|
function getBlockBufferOffset(component, row, col) {
|
||||||
return 64 * ((component.blocksPerLine + 1) * row + col);
|
return 64 * ((component.blocksPerLine + 1) * row + col);
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeScan(
|
function decodeScan(
|
||||||
data,
|
data,
|
||||||
offset,
|
offset,
|
||||||
frame,
|
frame,
|
||||||
@ -133,9 +124,9 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
successivePrev,
|
successivePrev,
|
||||||
successive,
|
successive,
|
||||||
parseDNLMarker = false
|
parseDNLMarker = false
|
||||||
) {
|
) {
|
||||||
var mcusPerLine = frame.mcusPerLine;
|
const mcusPerLine = frame.mcusPerLine;
|
||||||
var progressive = frame.progressive;
|
const progressive = frame.progressive;
|
||||||
|
|
||||||
const startOffset = offset;
|
const startOffset = offset;
|
||||||
let bitsData = 0,
|
let bitsData = 0,
|
||||||
@ -148,7 +139,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
bitsData = data[offset++];
|
bitsData = data[offset++];
|
||||||
if (bitsData === 0xff) {
|
if (bitsData === 0xff) {
|
||||||
var nextByte = data[offset++];
|
const nextByte = data[offset++];
|
||||||
if (nextByte) {
|
if (nextByte) {
|
||||||
if (nextByte === /* DNL = */ 0xdc && parseDNLMarker) {
|
if (nextByte === /* DNL = */ 0xdc && parseDNLMarker) {
|
||||||
offset += 2; // Skip marker length.
|
offset += 2; // Skip marker length.
|
||||||
@ -196,7 +187,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function decodeHuffman(tree) {
|
function decodeHuffman(tree) {
|
||||||
var node = tree;
|
let node = tree;
|
||||||
while (true) {
|
while (true) {
|
||||||
node = node[readBit()];
|
node = node[readBit()];
|
||||||
switch (typeof node) {
|
switch (typeof node) {
|
||||||
@ -210,7 +201,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function receive(length) {
|
function receive(length) {
|
||||||
var n = 0;
|
let n = 0;
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
n = (n << 1) | readBit();
|
n = (n << 1) | readBit();
|
||||||
length--;
|
length--;
|
||||||
@ -222,7 +213,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
if (length === 1) {
|
if (length === 1) {
|
||||||
return readBit() === 1 ? 1 : -1;
|
return readBit() === 1 ? 1 : -1;
|
||||||
}
|
}
|
||||||
var n = receive(length);
|
const n = receive(length);
|
||||||
if (n >= 1 << (length - 1)) {
|
if (n >= 1 << (length - 1)) {
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@ -230,13 +221,13 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function decodeBaseline(component, blockOffset) {
|
function decodeBaseline(component, blockOffset) {
|
||||||
var t = decodeHuffman(component.huffmanTableDC);
|
const t = decodeHuffman(component.huffmanTableDC);
|
||||||
var diff = t === 0 ? 0 : receiveAndExtend(t);
|
const diff = t === 0 ? 0 : receiveAndExtend(t);
|
||||||
component.blockData[blockOffset] = component.pred += diff;
|
component.blockData[blockOffset] = component.pred += diff;
|
||||||
var k = 1;
|
let k = 1;
|
||||||
while (k < 64) {
|
while (k < 64) {
|
||||||
var rs = decodeHuffman(component.huffmanTableAC);
|
const rs = decodeHuffman(component.huffmanTableAC);
|
||||||
var s = rs & 15,
|
const s = rs & 15,
|
||||||
r = rs >> 4;
|
r = rs >> 4;
|
||||||
if (s === 0) {
|
if (s === 0) {
|
||||||
if (r < 15) {
|
if (r < 15) {
|
||||||
@ -246,15 +237,15 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
k += r;
|
k += r;
|
||||||
var z = dctZigZag[k];
|
const z = dctZigZag[k];
|
||||||
component.blockData[blockOffset + z] = receiveAndExtend(s);
|
component.blockData[blockOffset + z] = receiveAndExtend(s);
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeDCFirst(component, blockOffset) {
|
function decodeDCFirst(component, blockOffset) {
|
||||||
var t = decodeHuffman(component.huffmanTableDC);
|
const t = decodeHuffman(component.huffmanTableDC);
|
||||||
var diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
|
const diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
|
||||||
component.blockData[blockOffset] = component.pred += diff;
|
component.blockData[blockOffset] = component.pred += diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,17 +253,17 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
component.blockData[blockOffset] |= readBit() << successive;
|
component.blockData[blockOffset] |= readBit() << successive;
|
||||||
}
|
}
|
||||||
|
|
||||||
var eobrun = 0;
|
let eobrun = 0;
|
||||||
function decodeACFirst(component, blockOffset) {
|
function decodeACFirst(component, blockOffset) {
|
||||||
if (eobrun > 0) {
|
if (eobrun > 0) {
|
||||||
eobrun--;
|
eobrun--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var k = spectralStart,
|
let k = spectralStart;
|
||||||
e = spectralEnd;
|
const e = spectralEnd;
|
||||||
while (k <= e) {
|
while (k <= e) {
|
||||||
var rs = decodeHuffman(component.huffmanTableAC);
|
const rs = decodeHuffman(component.huffmanTableAC);
|
||||||
var s = rs & 15,
|
const s = rs & 15,
|
||||||
r = rs >> 4;
|
r = rs >> 4;
|
||||||
if (s === 0) {
|
if (s === 0) {
|
||||||
if (r < 15) {
|
if (r < 15) {
|
||||||
@ -283,21 +274,21 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
k += r;
|
k += r;
|
||||||
var z = dctZigZag[k];
|
const z = dctZigZag[k];
|
||||||
component.blockData[blockOffset + z] =
|
component.blockData[blockOffset + z] =
|
||||||
receiveAndExtend(s) * (1 << successive);
|
receiveAndExtend(s) * (1 << successive);
|
||||||
k++;
|
k++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var successiveACState = 0,
|
let successiveACState = 0,
|
||||||
successiveACNextValue;
|
successiveACNextValue;
|
||||||
function decodeACSuccessive(component, blockOffset) {
|
function decodeACSuccessive(component, blockOffset) {
|
||||||
var k = spectralStart;
|
let k = spectralStart;
|
||||||
var e = spectralEnd;
|
const e = spectralEnd;
|
||||||
var r = 0;
|
let r = 0;
|
||||||
var s;
|
let s;
|
||||||
var rs;
|
let rs;
|
||||||
while (k <= e) {
|
while (k <= e) {
|
||||||
const offsetZ = blockOffset + dctZigZag[k];
|
const offsetZ = blockOffset + dctZigZag[k];
|
||||||
const sign = component.blockData[offsetZ] < 0 ? -1 : 1;
|
const sign = component.blockData[offsetZ] < 0 ? -1 : 1;
|
||||||
@ -337,8 +328,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
if (component.blockData[offsetZ]) {
|
if (component.blockData[offsetZ]) {
|
||||||
component.blockData[offsetZ] += sign * (readBit() << successive);
|
component.blockData[offsetZ] += sign * (readBit() << successive);
|
||||||
} else {
|
} else {
|
||||||
component.blockData[offsetZ] =
|
component.blockData[offsetZ] = successiveACNextValue << successive;
|
||||||
successiveACNextValue << successive;
|
|
||||||
successiveACState = 0;
|
successiveACState = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -360,24 +350,24 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
|
|
||||||
let blockRow = 0;
|
let blockRow = 0;
|
||||||
function decodeMcu(component, decode, mcu, row, col) {
|
function decodeMcu(component, decode, mcu, row, col) {
|
||||||
var mcuRow = (mcu / mcusPerLine) | 0;
|
const mcuRow = (mcu / mcusPerLine) | 0;
|
||||||
var mcuCol = mcu % mcusPerLine;
|
const mcuCol = mcu % mcusPerLine;
|
||||||
blockRow = mcuRow * component.v + row;
|
blockRow = mcuRow * component.v + row;
|
||||||
var blockCol = mcuCol * component.h + col;
|
const blockCol = mcuCol * component.h + col;
|
||||||
const blockOffset = getBlockBufferOffset(component, blockRow, blockCol);
|
const blockOffset = getBlockBufferOffset(component, blockRow, blockCol);
|
||||||
decode(component, blockOffset);
|
decode(component, blockOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
function decodeBlock(component, decode, mcu) {
|
function decodeBlock(component, decode, mcu) {
|
||||||
blockRow = (mcu / component.blocksPerLine) | 0;
|
blockRow = (mcu / component.blocksPerLine) | 0;
|
||||||
var blockCol = mcu % component.blocksPerLine;
|
const blockCol = mcu % component.blocksPerLine;
|
||||||
const blockOffset = getBlockBufferOffset(component, blockRow, blockCol);
|
const blockOffset = getBlockBufferOffset(component, blockRow, blockCol);
|
||||||
decode(component, blockOffset);
|
decode(component, blockOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
var componentsLength = components.length;
|
const componentsLength = components.length;
|
||||||
var component, i, j, k, n;
|
let component, i, j, k, n;
|
||||||
var decodeFn;
|
let decodeFn;
|
||||||
if (progressive) {
|
if (progressive) {
|
||||||
if (spectralStart === 0) {
|
if (spectralStart === 0) {
|
||||||
decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
|
decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
|
||||||
@ -388,19 +378,19 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
decodeFn = decodeBaseline;
|
decodeFn = decodeBaseline;
|
||||||
}
|
}
|
||||||
|
|
||||||
var mcu = 0,
|
let mcu = 0,
|
||||||
fileMarker;
|
fileMarker;
|
||||||
var mcuExpected;
|
let mcuExpected;
|
||||||
if (componentsLength === 1) {
|
if (componentsLength === 1) {
|
||||||
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
|
mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
|
||||||
} else {
|
} else {
|
||||||
mcuExpected = mcusPerLine * frame.mcusPerColumn;
|
mcuExpected = mcusPerLine * frame.mcusPerColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
var h, v;
|
let h, v;
|
||||||
while (mcu <= mcuExpected) {
|
while (mcu <= mcuExpected) {
|
||||||
// reset interval stuff
|
// reset interval stuff
|
||||||
var mcuToRead = resetInterval
|
const mcuToRead = resetInterval
|
||||||
? Math.min(mcuExpected - mcu, resetInterval)
|
? Math.min(mcuExpected - mcu, resetInterval)
|
||||||
: mcuExpected;
|
: mcuExpected;
|
||||||
|
|
||||||
@ -461,26 +451,26 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return offset - startOffset;
|
return offset - startOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
// A port of poppler's IDCT method which in turn is taken from:
|
// A port of poppler's IDCT method which in turn is taken from:
|
||||||
// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
|
// Christoph Loeffler, Adriaan Ligtenberg, George S. Moschytz,
|
||||||
// 'Practical Fast 1-D DCT Algorithms with 11 Multiplications',
|
// 'Practical Fast 1-D DCT Algorithms with 11 Multiplications',
|
||||||
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
|
// IEEE Intl. Conf. on Acoustics, Speech & Signal Processing, 1989,
|
||||||
// 988-991.
|
// 988-991.
|
||||||
function quantizeAndInverse(component, blockBufferOffset, p) {
|
function quantizeAndInverse(component, blockBufferOffset, p) {
|
||||||
var qt = component.quantizationTable,
|
const qt = component.quantizationTable,
|
||||||
blockData = component.blockData;
|
blockData = component.blockData;
|
||||||
var v0, v1, v2, v3, v4, v5, v6, v7;
|
let v0, v1, v2, v3, v4, v5, v6, v7;
|
||||||
var p0, p1, p2, p3, p4, p5, p6, p7;
|
let p0, p1, p2, p3, p4, p5, p6, p7;
|
||||||
var t;
|
let t;
|
||||||
|
|
||||||
if (!qt) {
|
if (!qt) {
|
||||||
throw new JpegError("missing required Quantization Table.");
|
throw new JpegError("missing required Quantization Table.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// inverse DCT on rows
|
// inverse DCT on rows
|
||||||
for (var row = 0; row < 64; row += 8) {
|
for (let row = 0; row < 64; row += 8) {
|
||||||
// gather block data
|
// gather block data
|
||||||
p0 = blockData[blockBufferOffset + row];
|
p0 = blockData[blockBufferOffset + row];
|
||||||
p1 = blockData[blockBufferOffset + row + 1];
|
p1 = blockData[blockBufferOffset + row + 1];
|
||||||
@ -561,7 +551,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// inverse DCT on columns
|
// inverse DCT on columns
|
||||||
for (var col = 0; col < 8; ++col) {
|
for (let col = 0; col < 8; ++col) {
|
||||||
p0 = p[col];
|
p0 = p[col];
|
||||||
p1 = p[col + 8];
|
p1 = p[col + 8];
|
||||||
p2 = p[col + 16];
|
p2 = p[col + 16];
|
||||||
@ -706,30 +696,30 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
blockData[blockBufferOffset + col + 48] = p6;
|
blockData[blockBufferOffset + col + 48] = p6;
|
||||||
blockData[blockBufferOffset + col + 56] = p7;
|
blockData[blockBufferOffset + col + 56] = p7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildComponentData(frame, component) {
|
function buildComponentData(frame, component) {
|
||||||
var blocksPerLine = component.blocksPerLine;
|
const blocksPerLine = component.blocksPerLine;
|
||||||
var blocksPerColumn = component.blocksPerColumn;
|
const blocksPerColumn = component.blocksPerColumn;
|
||||||
var computationBuffer = new Int16Array(64);
|
const computationBuffer = new Int16Array(64);
|
||||||
|
|
||||||
for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
|
for (let blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
|
||||||
for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
|
for (let blockCol = 0; blockCol < blocksPerLine; blockCol++) {
|
||||||
var offset = getBlockBufferOffset(component, blockRow, blockCol);
|
const offset = getBlockBufferOffset(component, blockRow, blockCol);
|
||||||
quantizeAndInverse(component, offset, computationBuffer);
|
quantizeAndInverse(component, offset, computationBuffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return component.blockData;
|
return component.blockData;
|
||||||
}
|
}
|
||||||
|
|
||||||
function findNextFileMarker(data, currentPos, startPos = currentPos) {
|
function findNextFileMarker(data, currentPos, startPos = currentPos) {
|
||||||
const maxPos = data.length - 1;
|
const maxPos = data.length - 1;
|
||||||
var newPos = startPos < currentPos ? startPos : currentPos;
|
let newPos = startPos < currentPos ? startPos : currentPos;
|
||||||
|
|
||||||
if (currentPos >= maxPos) {
|
if (currentPos >= maxPos) {
|
||||||
return null; // Don't attempt to read non-existent data and just return.
|
return null; // Don't attempt to read non-existent data and just return.
|
||||||
}
|
}
|
||||||
var currentMarker = readUint16(data, currentPos);
|
const currentMarker = readUint16(data, currentPos);
|
||||||
if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) {
|
if (currentMarker >= 0xffc0 && currentMarker <= 0xfffe) {
|
||||||
return {
|
return {
|
||||||
invalid: null,
|
invalid: null,
|
||||||
@ -737,7 +727,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
offset: currentPos,
|
offset: currentPos,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
var newMarker = readUint16(data, newPos);
|
let newMarker = readUint16(data, newPos);
|
||||||
while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) {
|
while (!(newMarker >= 0xffc0 && newMarker <= 0xfffe)) {
|
||||||
if (++newPos >= maxPos) {
|
if (++newPos >= maxPos) {
|
||||||
return null; // Don't attempt to read non-existent data and just return.
|
return null; // Don't attempt to read non-existent data and just return.
|
||||||
@ -749,16 +739,21 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
marker: newMarker,
|
marker: newMarker,
|
||||||
offset: newPos,
|
offset: newPos,
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class JpegImage {
|
||||||
|
constructor({ decodeTransform = null, colorTransform = -1 } = {}) {
|
||||||
|
this._decodeTransform = decodeTransform;
|
||||||
|
this._colorTransform = colorTransform;
|
||||||
}
|
}
|
||||||
|
|
||||||
JpegImage.prototype = {
|
|
||||||
parse(data, { dnlScanLines = null } = {}) {
|
parse(data, { dnlScanLines = null } = {}) {
|
||||||
function readDataBlock() {
|
function readDataBlock() {
|
||||||
const length = readUint16(data, offset);
|
const length = readUint16(data, offset);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
let endOffset = offset + length - 2;
|
let endOffset = offset + length - 2;
|
||||||
|
|
||||||
var fileMarker = findNextFileMarker(data, endOffset, offset);
|
const fileMarker = findNextFileMarker(data, endOffset, offset);
|
||||||
if (fileMarker && fileMarker.invalid) {
|
if (fileMarker && fileMarker.invalid) {
|
||||||
warn(
|
warn(
|
||||||
"readDataBlock - incorrect length, current marker is: " +
|
"readDataBlock - incorrect length, current marker is: " +
|
||||||
@ -767,26 +762,26 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
endOffset = fileMarker.offset;
|
endOffset = fileMarker.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
var array = data.subarray(offset, endOffset);
|
const array = data.subarray(offset, endOffset);
|
||||||
offset += array.length;
|
offset += array.length;
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
function prepareComponents(frame) {
|
function prepareComponents(frame) {
|
||||||
var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);
|
const mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);
|
||||||
var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
|
const mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
|
||||||
for (var i = 0; i < frame.components.length; i++) {
|
for (let i = 0, ii = frame.components.length; i < ii; i++) {
|
||||||
component = frame.components[i];
|
const component = frame.components[i];
|
||||||
var blocksPerLine = Math.ceil(
|
const blocksPerLine = Math.ceil(
|
||||||
(Math.ceil(frame.samplesPerLine / 8) * component.h) / frame.maxH
|
(Math.ceil(frame.samplesPerLine / 8) * component.h) / frame.maxH
|
||||||
);
|
);
|
||||||
var blocksPerColumn = Math.ceil(
|
const blocksPerColumn = Math.ceil(
|
||||||
(Math.ceil(frame.scanLines / 8) * component.v) / frame.maxV
|
(Math.ceil(frame.scanLines / 8) * component.v) / frame.maxV
|
||||||
);
|
);
|
||||||
var blocksPerLineForMcu = mcusPerLine * component.h;
|
const blocksPerLineForMcu = mcusPerLine * component.h;
|
||||||
var blocksPerColumnForMcu = mcusPerColumn * component.v;
|
const blocksPerColumnForMcu = mcusPerColumn * component.v;
|
||||||
|
|
||||||
var blocksBufferSize =
|
const blocksBufferSize =
|
||||||
64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
|
64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
|
||||||
component.blockData = new Int16Array(blocksBufferSize);
|
component.blockData = new Int16Array(blocksBufferSize);
|
||||||
component.blocksPerLine = blocksPerLine;
|
component.blocksPerLine = blocksPerLine;
|
||||||
@ -796,13 +791,13 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
frame.mcusPerColumn = mcusPerColumn;
|
frame.mcusPerColumn = mcusPerColumn;
|
||||||
}
|
}
|
||||||
|
|
||||||
var offset = 0;
|
let offset = 0;
|
||||||
var jfif = null;
|
let jfif = null;
|
||||||
var adobe = null;
|
let adobe = null;
|
||||||
var frame, resetInterval;
|
let frame, resetInterval;
|
||||||
let numSOSMarkers = 0;
|
let numSOSMarkers = 0;
|
||||||
var quantizationTables = [];
|
const quantizationTables = [];
|
||||||
var huffmanTablesAC = [],
|
const huffmanTablesAC = [],
|
||||||
huffmanTablesDC = [];
|
huffmanTablesDC = [];
|
||||||
|
|
||||||
let fileMarker = readUint16(data, offset);
|
let fileMarker = readUint16(data, offset);
|
||||||
@ -814,7 +809,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
offset += 2;
|
offset += 2;
|
||||||
|
|
||||||
markerLoop: while (fileMarker !== /* EOI (End of Image) = */ 0xffd9) {
|
markerLoop: while (fileMarker !== /* EOI (End of Image) = */ 0xffd9) {
|
||||||
var i, j, l;
|
let i, j, l;
|
||||||
switch (fileMarker) {
|
switch (fileMarker) {
|
||||||
case 0xffe0: // APP0 (Application Specific)
|
case 0xffe0: // APP0 (Application Specific)
|
||||||
case 0xffe1: // APP1
|
case 0xffe1: // APP1
|
||||||
@ -833,7 +828,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
case 0xffee: // APP14
|
case 0xffee: // APP14
|
||||||
case 0xffef: // APP15
|
case 0xffef: // APP15
|
||||||
case 0xfffe: // COM (Comment)
|
case 0xfffe: // COM (Comment)
|
||||||
var appData = readDataBlock();
|
const appData = readDataBlock();
|
||||||
|
|
||||||
if (fileMarker === 0xffe0) {
|
if (fileMarker === 0xffe0) {
|
||||||
// 'JFIF\x00'
|
// 'JFIF\x00'
|
||||||
@ -881,11 +876,11 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
case 0xffdb: // DQT (Define Quantization Tables)
|
case 0xffdb: // DQT (Define Quantization Tables)
|
||||||
const quantizationTablesLength = readUint16(data, offset);
|
const quantizationTablesLength = readUint16(data, offset);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
var quantizationTablesEnd = quantizationTablesLength + offset - 2;
|
const quantizationTablesEnd = quantizationTablesLength + offset - 2;
|
||||||
var z;
|
let z;
|
||||||
while (offset < quantizationTablesEnd) {
|
while (offset < quantizationTablesEnd) {
|
||||||
var quantizationTableSpec = data[offset++];
|
const quantizationTableSpec = data[offset++];
|
||||||
var tableData = new Uint16Array(64);
|
const tableData = new Uint16Array(64);
|
||||||
if (quantizationTableSpec >> 4 === 0) {
|
if (quantizationTableSpec >> 4 === 0) {
|
||||||
// 8 bit values
|
// 8 bit values
|
||||||
for (j = 0; j < 64; j++) {
|
for (j = 0; j < 64; j++) {
|
||||||
@ -925,21 +920,20 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
offset += 2;
|
offset += 2;
|
||||||
frame.components = [];
|
frame.components = [];
|
||||||
frame.componentIds = {};
|
frame.componentIds = {};
|
||||||
var componentsCount = data[offset++],
|
const componentsCount = data[offset++];
|
||||||
componentId;
|
let maxH = 0,
|
||||||
var maxH = 0,
|
|
||||||
maxV = 0;
|
maxV = 0;
|
||||||
for (i = 0; i < componentsCount; i++) {
|
for (i = 0; i < componentsCount; i++) {
|
||||||
componentId = data[offset];
|
const componentId = data[offset];
|
||||||
var h = data[offset + 1] >> 4;
|
const h = data[offset + 1] >> 4;
|
||||||
var v = data[offset + 1] & 15;
|
const v = data[offset + 1] & 15;
|
||||||
if (maxH < h) {
|
if (maxH < h) {
|
||||||
maxH = h;
|
maxH = h;
|
||||||
}
|
}
|
||||||
if (maxV < v) {
|
if (maxV < v) {
|
||||||
maxV = v;
|
maxV = v;
|
||||||
}
|
}
|
||||||
var qId = data[offset + 2];
|
const qId = data[offset + 2];
|
||||||
l = frame.components.push({
|
l = frame.components.push({
|
||||||
h,
|
h,
|
||||||
v,
|
v,
|
||||||
@ -958,13 +952,13 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
const huffmanLength = readUint16(data, offset);
|
const huffmanLength = readUint16(data, offset);
|
||||||
offset += 2;
|
offset += 2;
|
||||||
for (i = 2; i < huffmanLength; ) {
|
for (i = 2; i < huffmanLength; ) {
|
||||||
var huffmanTableSpec = data[offset++];
|
const huffmanTableSpec = data[offset++];
|
||||||
var codeLengths = new Uint8Array(16);
|
const codeLengths = new Uint8Array(16);
|
||||||
var codeLengthSum = 0;
|
let codeLengthSum = 0;
|
||||||
for (j = 0; j < 16; j++, offset++) {
|
for (j = 0; j < 16; j++, offset++) {
|
||||||
codeLengthSum += codeLengths[j] = data[offset];
|
codeLengthSum += codeLengths[j] = data[offset];
|
||||||
}
|
}
|
||||||
var huffmanValues = new Uint8Array(codeLengthSum);
|
const huffmanValues = new Uint8Array(codeLengthSum);
|
||||||
for (j = 0; j < codeLengthSum; j++, offset++) {
|
for (j = 0; j < codeLengthSum; j++, offset++) {
|
||||||
huffmanValues[j] = data[offset];
|
huffmanValues[j] = data[offset];
|
||||||
}
|
}
|
||||||
@ -992,24 +986,23 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
|
|
||||||
offset += 2; // Skip marker length.
|
offset += 2; // Skip marker length.
|
||||||
|
|
||||||
var selectorsCount = data[offset++];
|
const selectorsCount = data[offset++],
|
||||||
var components = [],
|
components = [];
|
||||||
component;
|
|
||||||
for (i = 0; i < selectorsCount; i++) {
|
for (i = 0; i < selectorsCount; i++) {
|
||||||
const index = data[offset++];
|
const index = data[offset++];
|
||||||
var componentIndex = frame.componentIds[index];
|
const componentIndex = frame.componentIds[index];
|
||||||
component = frame.components[componentIndex];
|
const component = frame.components[componentIndex];
|
||||||
component.index = index;
|
component.index = index;
|
||||||
var tableSpec = data[offset++];
|
const tableSpec = data[offset++];
|
||||||
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
|
component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
|
||||||
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
|
component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
|
||||||
components.push(component);
|
components.push(component);
|
||||||
}
|
}
|
||||||
var spectralStart = data[offset++];
|
const spectralStart = data[offset++],
|
||||||
var spectralEnd = data[offset++];
|
spectralEnd = data[offset++],
|
||||||
var successiveApproximation = data[offset++];
|
successiveApproximation = data[offset++];
|
||||||
try {
|
try {
|
||||||
var processed = decodeScan(
|
const processed = decodeScan(
|
||||||
data,
|
data,
|
||||||
offset,
|
offset,
|
||||||
frame,
|
frame,
|
||||||
@ -1083,13 +1076,13 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
this.jfif = jfif;
|
this.jfif = jfif;
|
||||||
this.adobe = adobe;
|
this.adobe = adobe;
|
||||||
this.components = [];
|
this.components = [];
|
||||||
for (i = 0; i < frame.components.length; i++) {
|
for (let i = 0, ii = frame.components.length; i < ii; i++) {
|
||||||
component = frame.components[i];
|
const component = frame.components[i];
|
||||||
|
|
||||||
// Prevent errors when DQT markers are placed after SOF{n} markers,
|
// Prevent errors when DQT markers are placed after SOF{n} markers,
|
||||||
// by assigning the `quantizationTable` entry after the entire image
|
// by assigning the `quantizationTable` entry after the entire image
|
||||||
// has been parsed (fixes issue7406.pdf).
|
// has been parsed (fixes issue7406.pdf).
|
||||||
var quantizationTable = quantizationTables[component.quantizationId];
|
const quantizationTable = quantizationTables[component.quantizationId];
|
||||||
if (quantizationTable) {
|
if (quantizationTable) {
|
||||||
component.quantizationTable = quantizationTable;
|
component.quantizationTable = quantizationTable;
|
||||||
}
|
}
|
||||||
@ -1105,22 +1098,22 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
this.numComponents = this.components.length;
|
this.numComponents = this.components.length;
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
}
|
||||||
|
|
||||||
_getLinearizedBlockData(width, height, isSourcePDF = false) {
|
_getLinearizedBlockData(width, height, isSourcePDF = false) {
|
||||||
var scaleX = this.width / width,
|
const scaleX = this.width / width,
|
||||||
scaleY = this.height / height;
|
scaleY = this.height / height;
|
||||||
|
|
||||||
var component, componentScaleX, componentScaleY, blocksPerScanline;
|
let component, componentScaleX, componentScaleY, blocksPerScanline;
|
||||||
var x, y, i, j, k;
|
let x, y, i, j, k;
|
||||||
var index;
|
let index;
|
||||||
var offset = 0;
|
let offset = 0;
|
||||||
var output;
|
let output;
|
||||||
var numComponents = this.components.length;
|
const numComponents = this.components.length;
|
||||||
var dataLength = width * height * numComponents;
|
const dataLength = width * height * numComponents;
|
||||||
var data = new Uint8ClampedArray(dataLength);
|
const data = new Uint8ClampedArray(dataLength);
|
||||||
var xScaleBlockOffset = new Uint32Array(width);
|
const xScaleBlockOffset = new Uint32Array(width);
|
||||||
var mask3LSB = 0xfffffff8; // used to clear the 3 LSBs
|
const mask3LSB = 0xfffffff8; // used to clear the 3 LSBs
|
||||||
let lastComponentScaleX;
|
let lastComponentScaleX;
|
||||||
|
|
||||||
for (i = 0; i < numComponents; i++) {
|
for (i = 0; i < numComponents; i++) {
|
||||||
@ -1178,7 +1171,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
},
|
}
|
||||||
|
|
||||||
get _isColorConversionNeeded() {
|
get _isColorConversionNeeded() {
|
||||||
if (this.adobe) {
|
if (this.adobe) {
|
||||||
@ -1210,11 +1203,11 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
},
|
}
|
||||||
|
|
||||||
_convertYccToRgb: function convertYccToRgb(data) {
|
_convertYccToRgb(data) {
|
||||||
var Y, Cb, Cr;
|
let Y, Cb, Cr;
|
||||||
for (var i = 0, length = data.length; i < length; i += 3) {
|
for (let i = 0, length = data.length; i < length; i += 3) {
|
||||||
Y = data[i];
|
Y = data[i];
|
||||||
Cb = data[i + 1];
|
Cb = data[i + 1];
|
||||||
Cr = data[i + 2];
|
Cr = data[i + 2];
|
||||||
@ -1223,12 +1216,12 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
data[i + 2] = Y - 226.816 + 1.772 * Cb;
|
data[i + 2] = Y - 226.816 + 1.772 * Cb;
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
},
|
}
|
||||||
|
|
||||||
_convertYcckToRgb: function convertYcckToRgb(data) {
|
_convertYcckToRgb(data) {
|
||||||
var Y, Cb, Cr, k;
|
let Y, Cb, Cr, k;
|
||||||
var offset = 0;
|
let offset = 0;
|
||||||
for (var i = 0, length = data.length; i < length; i += 4) {
|
for (let i = 0, length = data.length; i < length; i += 4) {
|
||||||
Y = data[i];
|
Y = data[i];
|
||||||
Cb = data[i + 1];
|
Cb = data[i + 1];
|
||||||
Cr = data[i + 2];
|
Cr = data[i + 2];
|
||||||
@ -1293,11 +1286,11 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
// Ensure that only the converted RGB data is returned.
|
// Ensure that only the converted RGB data is returned.
|
||||||
return data.subarray(0, offset);
|
return data.subarray(0, offset);
|
||||||
},
|
}
|
||||||
|
|
||||||
_convertYcckToCmyk: function convertYcckToCmyk(data) {
|
_convertYcckToCmyk(data) {
|
||||||
var Y, Cb, Cr;
|
let Y, Cb, Cr;
|
||||||
for (var i = 0, length = data.length; i < length; i += 4) {
|
for (let i = 0, length = data.length; i < length; i += 4) {
|
||||||
Y = data[i];
|
Y = data[i];
|
||||||
Cb = data[i + 1];
|
Cb = data[i + 1];
|
||||||
Cr = data[i + 2];
|
Cr = data[i + 2];
|
||||||
@ -1307,12 +1300,12 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
// K in data[i + 3] is unchanged
|
// K in data[i + 3] is unchanged
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
},
|
}
|
||||||
|
|
||||||
_convertCmykToRgb: function convertCmykToRgb(data) {
|
_convertCmykToRgb(data) {
|
||||||
var c, m, y, k;
|
let c, m, y, k;
|
||||||
var offset = 0;
|
let offset = 0;
|
||||||
for (var i = 0, length = data.length; i < length; i += 4) {
|
for (let i = 0, length = data.length; i < length; i += 4) {
|
||||||
c = data[i];
|
c = data[i];
|
||||||
m = data[i + 1];
|
m = data[i + 1];
|
||||||
y = data[i + 2];
|
y = data[i + 2];
|
||||||
@ -1377,7 +1370,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
// Ensure that only the converted RGB data is returned.
|
// Ensure that only the converted RGB data is returned.
|
||||||
return data.subarray(0, offset);
|
return data.subarray(0, offset);
|
||||||
},
|
}
|
||||||
|
|
||||||
getData({ width, height, forceRGB = false, isSourcePDF = false }) {
|
getData({ width, height, forceRGB = false, isSourcePDF = false }) {
|
||||||
if (
|
if (
|
||||||
@ -1393,14 +1386,14 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
throw new JpegError("Unsupported color mode");
|
throw new JpegError("Unsupported color mode");
|
||||||
}
|
}
|
||||||
// Type of data: Uint8ClampedArray(width * height * numComponents)
|
// Type of data: Uint8ClampedArray(width * height * numComponents)
|
||||||
var data = this._getLinearizedBlockData(width, height, isSourcePDF);
|
const data = this._getLinearizedBlockData(width, height, isSourcePDF);
|
||||||
|
|
||||||
if (this.numComponents === 1 && forceRGB) {
|
if (this.numComponents === 1 && forceRGB) {
|
||||||
var dataLength = data.length;
|
const dataLength = data.length;
|
||||||
var rgbData = new Uint8ClampedArray(dataLength * 3);
|
const rgbData = new Uint8ClampedArray(dataLength * 3);
|
||||||
var offset = 0;
|
let offset = 0;
|
||||||
for (var i = 0; i < dataLength; i++) {
|
for (let i = 0; i < dataLength; i++) {
|
||||||
var grayColor = data[i];
|
const grayColor = data[i];
|
||||||
rgbData[offset++] = grayColor;
|
rgbData[offset++] = grayColor;
|
||||||
rgbData[offset++] = grayColor;
|
rgbData[offset++] = grayColor;
|
||||||
rgbData[offset++] = grayColor;
|
rgbData[offset++] = grayColor;
|
||||||
@ -1419,10 +1412,7 @@ var JpegImage = (function JpegImageClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data;
|
return data;
|
||||||
},
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
return JpegImage;
|
|
||||||
})();
|
|
||||||
|
|
||||||
export { JpegImage };
|
export { JpegImage };
|
||||||
|
1211
src/core/jpx.js
1211
src/core/jpx.js
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user