diff --git a/external/jpgjs/jpg.js b/external/jpgjs/jpg.js index b6bb62391..549097b26 100644 --- a/external/jpgjs/jpg.js +++ b/external/jpgjs/jpg.js @@ -156,7 +156,7 @@ var JpegImage = (function jpegImage() { function decodeBaseline(component, offset) { var t = decodeHuffman(component.huffmanTableDC); var diff = t === 0 ? 0 : receiveAndExtend(t); - component.blocks[offset] = (component.pred += diff); + component.blockData[offset] = (component.pred += diff); var k = 1; while (k < 64) { var rs = decodeHuffman(component.huffmanTableAC); @@ -169,7 +169,7 @@ var JpegImage = (function jpegImage() { } k += r; var z = dctZigZag[k]; - component.blocks[offset + z] = receiveAndExtend(s); + component.blockData[offset + z] = receiveAndExtend(s); k++; } } @@ -177,11 +177,11 @@ var JpegImage = (function jpegImage() { function decodeDCFirst(component, offset) { var t = decodeHuffman(component.huffmanTableDC); var diff = t === 0 ? 0 : (receiveAndExtend(t) << successive); - component.blocks[offset] = (component.pred += diff); + component.blockData[offset] = (component.pred += diff); } function decodeDCSuccessive(component, offset) { - component.blocks[offset] |= readBit() << successive; + component.blockData[offset] |= readBit() << successive; } var eobrun = 0; @@ -204,7 +204,7 @@ var JpegImage = (function jpegImage() { } k += r; var z = dctZigZag[k]; - component.blocks[offset + z] = receiveAndExtend(s) * (1 << successive); + component.blockData[offset + z] = receiveAndExtend(s) * (1 << successive); k++; } } @@ -235,8 +235,8 @@ var JpegImage = (function jpegImage() { continue; case 1: // skipping r zero items case 2: - if (component.blocks[offset + z]) { - component.blocks[offset + z] += (readBit() << successive); + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); } else { r--; if (r === 0) @@ -244,16 +244,16 @@ var JpegImage = (function jpegImage() { } break; case 3: // set value for a zero item - if (component.blocks[offset + z]) { - component.blocks[offset + z] += (readBit() << successive); + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); } else { - component.blocks[offset + z] = successiveACNextValue << successive; + component.blockData[offset + z] = successiveACNextValue << successive; successiveACState = 0; } break; case 4: // eob - if (component.blocks[offset + z]) { - component.blocks[offset + z] += (readBit() << successive); + if (component.blockData[offset + z]) { + component.blockData[offset + z] += (readBit() << successive); } break; } @@ -363,8 +363,9 @@ var JpegImage = (function jpegImage() { var i; // dequant - for (i = 0; i < 64; i++) - p[i] = component.blocks[blockBufferOffset + i] * qt[i]; + for (i = 0; i < 64; i++) { + p[i] = component.blockData[blockBufferOffset + i] * qt[i]; + } // inverse DCT on rows for (i = 0; i < 8; ++i) { @@ -506,7 +507,8 @@ var JpegImage = (function jpegImage() { // convert to 8-bit integers for (i = 0; i < 64; ++i) { - p[i] = clampTo8bit((p[i] + 2056) >> 4); + var index = blockBufferOffset + i; + component.blockData[index] = clampTo8bitInt((p[i] + 2056) >> 4); } } @@ -515,35 +517,26 @@ var JpegImage = (function jpegImage() { var blocksPerLine = component.blocksPerLine; var blocksPerColumn = component.blocksPerColumn; var samplesPerLine = blocksPerLine << 3; - var R = new Int16Array(64); + var computationBuffer = new Int32Array(64); var i, j, ll = 0; for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { - var scanLine = blockRow << 3; - for (i = 0; i < 8; i++) { - lines[ll++] = new Uint8Array(samplesPerLine); - } for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { - - quantizeAndInverse(component, - getBlockBufferOffset(component, 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++]; - } - } + var offset = getBlockBufferOffset(component, blockRow, blockCol) + quantizeAndInverse(component, offset, computationBuffer); } } - return lines; + return component.blockData; } - function clampTo8bit(a) { + function clampTo8bitInt(a) { return a <= 0 ? 0 : a >= 255 ? 255 : a | 0; } + function clamp0to255(a) { + return a <= 0 ? 0 : a >= 255 ? 255 : a; + } + constructor.prototype = { load: function load(path) { var xhr = new XMLHttpRequest(); @@ -586,11 +579,9 @@ var JpegImage = (function jpegImage() { var blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1); - var blocks = new Int16Array(blocksBufferSize); - + component.blockData = new Int16Array(blocksBufferSize); component.blocksPerLine = blocksPerLine; component.blocksPerColumn = blocksPerColumn; - component.blocks = blocks; } frame.mcusPerLine = mcusPerLine; frame.mcusPerColumn = mcusPerColumn; @@ -784,16 +775,19 @@ var JpegImage = (function jpegImage() { for (var i = 0; i < frame.components.length; i++) { var component = frame.components[i]; this.components.push({ - lines: buildComponentData(frame, component), + output: buildComponentData(frame, component), scaleX: component.h / frame.maxH, - scaleY: component.v / frame.maxV + scaleY: component.v / frame.maxV, + blocksPerLine: component.blocksPerLine, + blocksPerColumn: component.blocksPerColumn }); } }, + getData: function getData(width, height) { var scaleX = this.width / width, scaleY = this.height / height; - var component, componentLine, componentScaleX, componentScaleY; + var component, componentScaleX, componentScaleY; var x, y, i; var offset = 0; var Y, Cb, Cr, K, C, M, Ye, R, G, B; @@ -801,17 +795,49 @@ var JpegImage = (function jpegImage() { var numComponents = this.components.length; var dataLength = width * height * numComponents; var data = new Uint8Array(dataLength); + var componentLine; + + // lineData is reused for all components. Assume first component is + // the biggest + var lineData = new Uint8Array((this.components[0].blocksPerLine << 3) * + this.components[0].blocksPerColumn * 8); // First construct image data ... for (i = 0; i < numComponents; i++) { component = this.components[i]; + var blocksPerLine = component.blocksPerLine; + var blocksPerColumn = component.blocksPerColumn; + var samplesPerLine = blocksPerLine << 3; + + var j, k, ll = 0; + var lineOffset = 0; + for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) { + var scanLine = blockRow << 3; + for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) { + var bufferOffset = getBlockBufferOffset(component, blockRow, blockCol); + var offset = 0, sample = blockCol << 3; + for (j = 0; j < 8; j++) { + var lineOffset = (scanLine + j) * samplesPerLine; + for (k = 0; k < 8; k++) { + lineData[lineOffset + sample + k] = + component.output[bufferOffset + offset++]; + } + } + } + } + componentScaleX = component.scaleX * scaleX; componentScaleY = component.scaleY * scaleY; offset = i; + + var cx, cy; + var index; for (y = 0; y < height; y++) { - componentLine = component.lines[0 | (y * componentScaleY)]; for (x = 0; x < width; x++) { - data[offset] = componentLine[0 | (x * componentScaleX)]; + cy = 0 | (y * componentScaleY); + cx = 0 | (x * componentScaleX); + index = cy * samplesPerLine + cx; + data[offset] = lineData[index]; offset += numComponents; } } @@ -837,9 +863,9 @@ var JpegImage = (function jpegImage() { 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)); + R = clamp0to255(Y + 1.402 * (Cr - 128)); + G = clamp0to255(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128)); + B = clamp0to255(Y + 1.772 * (Cb - 128)); data[i ] = R; data[i + 1] = G; @@ -862,9 +888,9 @@ var JpegImage = (function jpegImage() { 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)); + C = 255 - clamp0to255(Y + 1.402 * (Cr - 128)); + M = 255 - clamp0to255(Y - 0.3441363 * (Cb - 128) - 0.71413636 * (Cr - 128)); + Ye = 255 - clamp0to255(Y + 1.772 * (Cb - 128)); data[i ] = C; data[i + 1] = M; @@ -915,9 +941,9 @@ var JpegImage = (function jpegImage() { Y = data[i++]; K = data[i++]; - R = 255 - clampTo8bit(C * (1 - K / 255) + K); - G = 255 - clampTo8bit(M * (1 - K / 255) + K); - B = 255 - clampTo8bit(Y * (1 - K / 255) + K); + R = 255 - clamp0to255(C * (1 - K / 255) + K); + G = 255 - clamp0to255(M * (1 - K / 255) + K); + B = 255 - clamp0to255(Y * (1 - K / 255) + K); imageDataArray[j++] = R; imageDataArray[j++] = G;