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