jpgjs performance tuning
This commit is contained in:
parent
35f5a1ea5e
commit
e874b272bf
204
external/jpgjs/jpg.js
vendored
204
external/jpgjs/jpg.js
vendored
@ -335,17 +335,16 @@ var JpegImage = (function jpegImage() {
|
|||||||
var blocksPerLine = component.blocksPerLine;
|
var blocksPerLine = component.blocksPerLine;
|
||||||
var blocksPerColumn = component.blocksPerColumn;
|
var blocksPerColumn = component.blocksPerColumn;
|
||||||
var samplesPerLine = blocksPerLine << 3;
|
var samplesPerLine = blocksPerLine << 3;
|
||||||
var R = new Int32Array(64), r = new Uint8Array(64);
|
var R = new Int32Array(64);
|
||||||
|
|
||||||
// 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(zz, dataOut, dataIn) {
|
function quantizeAndInverse(zz, p) {
|
||||||
var qt = component.quantizationTable;
|
var qt = component.quantizationTable;
|
||||||
var v0, v1, v2, v3, v4, v5, v6, v7, t;
|
var v0, v1, v2, v3, v4, v5, v6, v7, t;
|
||||||
var p = dataIn;
|
|
||||||
var i;
|
var i;
|
||||||
|
|
||||||
// dequant
|
// dequant
|
||||||
@ -429,7 +428,7 @@ var JpegImage = (function jpegImage() {
|
|||||||
if (p[1*8 + col] == 0 && p[2*8 + col] == 0 && p[3*8 + col] == 0 &&
|
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[4*8 + col] == 0 && p[5*8 + col] == 0 && p[6*8 + col] == 0 &&
|
||||||
p[7*8 + col] == 0) {
|
p[7*8 + col] == 0) {
|
||||||
t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14;
|
t = (dctSqrt2 * p[i+0] + 8192) >> 14;
|
||||||
p[0*8 + col] = t;
|
p[0*8 + col] = t;
|
||||||
p[1*8 + col] = t;
|
p[1*8 + col] = t;
|
||||||
p[2*8 + col] = t;
|
p[2*8 + col] = t;
|
||||||
@ -492,8 +491,7 @@ var JpegImage = (function jpegImage() {
|
|||||||
|
|
||||||
// convert to 8-bit integers
|
// convert to 8-bit integers
|
||||||
for (i = 0; i < 64; ++i) {
|
for (i = 0; i < 64; ++i) {
|
||||||
var sample = 128 + ((p[i] + 8) >> 4);
|
p[i] = clampTo8bit((p[i] + 2056) >> 4);
|
||||||
dataOut[i] = sample < 0 ? 0 : sample > 0xFF ? 0xFF : sample;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,13 +501,13 @@ var JpegImage = (function jpegImage() {
|
|||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
lines.push(new Uint8Array(samplesPerLine));
|
lines.push(new Uint8Array(samplesPerLine));
|
||||||
for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
|
for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
|
||||||
quantizeAndInverse(component.blocks[blockRow][blockCol], r, R);
|
quantizeAndInverse(component.blocks[blockRow][blockCol], R);
|
||||||
|
|
||||||
var offset = 0, sample = blockCol << 3;
|
var offset = 0, sample = blockCol << 3;
|
||||||
for (j = 0; j < 8; j++) {
|
for (j = 0; j < 8; j++) {
|
||||||
var line = lines[scanLine + j];
|
var line = lines[scanLine + j];
|
||||||
for (i = 0; i < 8; i++)
|
for (i = 0; i < 8; i++)
|
||||||
line[sample + i] = r[offset++];
|
line[sample + i] = R[offset++];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -570,7 +568,7 @@ var JpegImage = (function jpegImage() {
|
|||||||
for (var i = 0; i < blocksPerColumnForMcu; i++) {
|
for (var i = 0; i < blocksPerColumnForMcu; i++) {
|
||||||
var row = [];
|
var row = [];
|
||||||
for (var j = 0; j < blocksPerLineForMcu; j++)
|
for (var j = 0; j < blocksPerLineForMcu; j++)
|
||||||
row.push(new Int32Array(64));
|
row.push(new Int16Array(64));
|
||||||
blocks.push(row);
|
blocks.push(row);
|
||||||
}
|
}
|
||||||
component.blocksPerLine = blocksPerLine;
|
component.blocksPerLine = blocksPerLine;
|
||||||
@ -774,41 +772,35 @@ var JpegImage = (function jpegImage() {
|
|||||||
getData: function getData(width, height) {
|
getData: function getData(width, height) {
|
||||||
var scaleX = this.width / width, scaleY = this.height / height;
|
var scaleX = this.width / width, scaleY = this.height / height;
|
||||||
|
|
||||||
var component1, component2, component3, component4;
|
var component, componentLine, componentScaleX, componentScaleY;
|
||||||
var component1Line, component2Line, component3Line, component4Line;
|
var x, y, i;
|
||||||
var x, y;
|
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
var Y, Cb, Cr, K, C, M, Ye, R, G, B;
|
var Y, Cb, Cr, K, C, M, Ye, R, G, B;
|
||||||
var colorTransform;
|
var colorTransform;
|
||||||
var dataLength = width * height * this.components.length;
|
var numComponents = this.components.length;
|
||||||
|
var dataLength = width * height * numComponents;
|
||||||
var data = new Uint8Array(dataLength);
|
var data = new Uint8Array(dataLength);
|
||||||
switch (this.components.length) {
|
|
||||||
case 1:
|
|
||||||
component1 = this.components[0];
|
|
||||||
for (y = 0; y < height; y++) {
|
|
||||||
component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
|
|
||||||
for (x = 0; x < width; x++) {
|
|
||||||
Y = component1Line[0 | (x * component1.scaleX * scaleX)];
|
|
||||||
|
|
||||||
data[offset++] = Y;
|
// First construct image data ...
|
||||||
}
|
for (i = 0; i < numComponents; i++) {
|
||||||
|
component = this.components[i];
|
||||||
|
componentScaleX = component.scaleX * scaleX;
|
||||||
|
componentScaleY = component.scaleY * scaleY;
|
||||||
|
offset = i;
|
||||||
|
for (y = 0; y < height; y++) {
|
||||||
|
componentLine = component.lines[0 | (y * componentScaleY)];
|
||||||
|
for (x = 0; x < width; x++) {
|
||||||
|
data[offset] = componentLine[0 | (x * componentScaleX)];
|
||||||
|
offset += numComponents;
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
case 2:
|
}
|
||||||
// PDF might compress two component data in custom colorspace
|
|
||||||
component1 = this.components[0];
|
// ... then transform colors, if necessary
|
||||||
component2 = this.components[1];
|
switch (numComponents) {
|
||||||
for (y = 0; y < height; y++) {
|
case 1: case 2: break;
|
||||||
component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
|
// no color conversion for one or two compoenents
|
||||||
component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
|
|
||||||
for (x = 0; x < width; x++) {
|
|
||||||
Y = component1Line[0 | (x * component1.scaleX * scaleX)];
|
|
||||||
data[offset++] = Y;
|
|
||||||
Y = component2Line[0 | (x * component2.scaleX * scaleX)];
|
|
||||||
data[offset++] = Y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 3:
|
case 3:
|
||||||
// The default transform for three components is true
|
// The default transform for three components is true
|
||||||
colorTransform = true;
|
colorTransform = true;
|
||||||
@ -818,31 +810,19 @@ var JpegImage = (function jpegImage() {
|
|||||||
else if (typeof this.colorTransform !== 'undefined')
|
else if (typeof this.colorTransform !== 'undefined')
|
||||||
colorTransform = !!this.colorTransform;
|
colorTransform = !!this.colorTransform;
|
||||||
|
|
||||||
component1 = this.components[0];
|
if (colorTransform) {
|
||||||
component2 = this.components[1];
|
for (i = 0; i < dataLength; i += numComponents) {
|
||||||
component3 = this.components[2];
|
Y = data[i ];
|
||||||
for (y = 0; y < height; y++) {
|
Cb = data[i + 1];
|
||||||
component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
|
Cr = data[i + 2];
|
||||||
component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
|
|
||||||
component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)];
|
|
||||||
for (x = 0; x < width; x++) {
|
|
||||||
if (!colorTransform) {
|
|
||||||
R = component1Line[0 | (x * component1.scaleX * scaleX)];
|
|
||||||
G = component2Line[0 | (x * component2.scaleX * scaleX)];
|
|
||||||
B = component3Line[0 | (x * component3.scaleX * scaleX)];
|
|
||||||
} else {
|
|
||||||
Y = component1Line[0 | (x * component1.scaleX * scaleX)];
|
|
||||||
Cb = component2Line[0 | (x * component2.scaleX * scaleX)];
|
|
||||||
Cr = component3Line[0 | (x * component3.scaleX * scaleX)];
|
|
||||||
|
|
||||||
R = clampTo8bit(Y + 1.402 * (Cr - 128));
|
R = clampTo8bit(Y + 1.402 * (Cr - 128));
|
||||||
G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
|
G = clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
|
||||||
B = clampTo8bit(Y + 1.772 * (Cb - 128));
|
B = clampTo8bit(Y + 1.772 * (Cb - 128));
|
||||||
}
|
|
||||||
|
|
||||||
data[offset++] = R;
|
data[i ] = R;
|
||||||
data[offset++] = G;
|
data[i + 1] = G;
|
||||||
data[offset++] = B;
|
data[i + 2] = B;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -855,35 +835,20 @@ var JpegImage = (function jpegImage() {
|
|||||||
else if (typeof this.colorTransform !== 'undefined')
|
else if (typeof this.colorTransform !== 'undefined')
|
||||||
colorTransform = !!this.colorTransform;
|
colorTransform = !!this.colorTransform;
|
||||||
|
|
||||||
component1 = this.components[0];
|
if (colorTransform) {
|
||||||
component2 = this.components[1];
|
for (i = 0; i < dataLength; i += numComponents) {
|
||||||
component3 = this.components[2];
|
Y = data[i];
|
||||||
component4 = this.components[3];
|
Cb = data[i + 1];
|
||||||
for (y = 0; y < height; y++) {
|
Cr = data[i + 2];
|
||||||
component1Line = component1.lines[0 | (y * component1.scaleY * scaleY)];
|
|
||||||
component2Line = component2.lines[0 | (y * component2.scaleY * scaleY)];
|
|
||||||
component3Line = component3.lines[0 | (y * component3.scaleY * scaleY)];
|
|
||||||
component4Line = component4.lines[0 | (y * component4.scaleY * scaleY)];
|
|
||||||
for (x = 0; x < width; x++) {
|
|
||||||
if (!colorTransform) {
|
|
||||||
C = component1Line[0 | (x * component1.scaleX * scaleX)];
|
|
||||||
M = component2Line[0 | (x * component2.scaleX * scaleX)];
|
|
||||||
Ye = component3Line[0 | (x * component3.scaleX * scaleX)];
|
|
||||||
K = component4Line[0 | (x * component4.scaleX * scaleX)];
|
|
||||||
} else {
|
|
||||||
Y = component1Line[0 | (x * component1.scaleX * scaleX)];
|
|
||||||
Cb = component2Line[0 | (x * component2.scaleX * scaleX)];
|
|
||||||
Cr = component3Line[0 | (x * component3.scaleX * scaleX)];
|
|
||||||
K = component4Line[0 | (x * component4.scaleX * scaleX)];
|
|
||||||
|
|
||||||
C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128));
|
C = 255 - clampTo8bit(Y + 1.402 * (Cr - 128));
|
||||||
M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
|
M = 255 - clampTo8bit(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128));
|
||||||
Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128));
|
Ye = 255 - clampTo8bit(Y + 1.772 * (Cb - 128));
|
||||||
}
|
|
||||||
data[offset++] = C;
|
data[i ] = C;
|
||||||
data[offset++] = M;
|
data[i + 1] = M;
|
||||||
data[offset++] = Ye;
|
data[i + 2] = Ye;
|
||||||
data[offset++] = K;
|
// K is unchanged
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -894,54 +859,49 @@ var JpegImage = (function jpegImage() {
|
|||||||
},
|
},
|
||||||
copyToImageData: function copyToImageData(imageData) {
|
copyToImageData: function copyToImageData(imageData) {
|
||||||
var width = imageData.width, height = imageData.height;
|
var width = imageData.width, height = imageData.height;
|
||||||
|
var imageDataBytes = width * height * 4;
|
||||||
var imageDataArray = imageData.data;
|
var imageDataArray = imageData.data;
|
||||||
var data = this.getData(width, height);
|
var data = this.getData(width, height);
|
||||||
var i = 0, j = 0, x, y;
|
var i = 0, j = 0;
|
||||||
var Y, K, C, M, R, G, B;
|
var Y, K, C, M, R, G, B;
|
||||||
switch (this.components.length) {
|
switch (this.components.length) {
|
||||||
case 1:
|
case 1:
|
||||||
for (y = 0; y < height; y++) {
|
while (j < imageDataBytes) {
|
||||||
for (x = 0; x < width; x++) {
|
Y = data[i++];
|
||||||
Y = data[i++];
|
|
||||||
|
|
||||||
imageDataArray[j++] = Y;
|
imageDataArray[j++] = Y;
|
||||||
imageDataArray[j++] = Y;
|
imageDataArray[j++] = Y;
|
||||||
imageDataArray[j++] = Y;
|
imageDataArray[j++] = Y;
|
||||||
imageDataArray[j++] = 255;
|
imageDataArray[j++] = 255;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
for (y = 0; y < height; y++) {
|
while (j < imageDataBytes) {
|
||||||
for (x = 0; x < width; x++) {
|
R = data[i++];
|
||||||
R = data[i++];
|
G = data[i++];
|
||||||
G = data[i++];
|
B = data[i++];
|
||||||
B = data[i++];
|
|
||||||
|
|
||||||
imageDataArray[j++] = R;
|
imageDataArray[j++] = R;
|
||||||
imageDataArray[j++] = G;
|
imageDataArray[j++] = G;
|
||||||
imageDataArray[j++] = B;
|
imageDataArray[j++] = B;
|
||||||
imageDataArray[j++] = 255;
|
imageDataArray[j++] = 255;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
for (y = 0; y < height; y++) {
|
while (j < imageDataBytes) {
|
||||||
for (x = 0; x < width; x++) {
|
C = data[i++];
|
||||||
C = data[i++];
|
M = data[i++];
|
||||||
M = data[i++];
|
Y = data[i++];
|
||||||
Y = data[i++];
|
K = data[i++];
|
||||||
K = data[i++];
|
|
||||||
|
|
||||||
R = 255 - clampTo8bit(C * (1 - K / 255) + K);
|
R = 255 - clampTo8bit(C * (1 - K / 255) + K);
|
||||||
G = 255 - clampTo8bit(M * (1 - K / 255) + K);
|
G = 255 - clampTo8bit(M * (1 - K / 255) + K);
|
||||||
B = 255 - clampTo8bit(Y * (1 - K / 255) + K);
|
B = 255 - clampTo8bit(Y * (1 - K / 255) + K);
|
||||||
|
|
||||||
imageDataArray[j++] = R;
|
imageDataArray[j++] = R;
|
||||||
imageDataArray[j++] = G;
|
imageDataArray[j++] = G;
|
||||||
imageDataArray[j++] = B;
|
imageDataArray[j++] = B;
|
||||||
imageDataArray[j++] = 255;
|
imageDataArray[j++] = 255;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user