diff --git a/src/core/jpx.js b/src/core/jpx.js index 34d9d2e6e..abaa0f1da 100644 --- a/src/core/jpx.js +++ b/src/core/jpx.js @@ -50,6 +50,14 @@ var JpxImage = (function JpxImageClosure() { n = n * 256 + (data[offset + i] & 0xFF); return n; } + + var head = readUint(data, 0, 2); + // No box header, immediate start of codestream (SOC) + if (head === 0xFF4F) { + this.parseCodestream(data, 0, data.length); + return; + } + var position = 0, length = data.length; while (position < length) { var headerSize = 8; @@ -254,9 +262,9 @@ var JpxImage = (function JpxImageClosure() { cod.segmentationSymbolUsed = !!(blockStyle & 32); cod.transformation = data[j++]; if (cod.entropyCoderWithCustomPrecincts) { - var precinctsSizes = {}; + var precinctsSizes = []; while (j < length + position) { - var precinctsSize = data[j]; + var precinctsSize = data[j++]; precinctsSizes.push({ PPx: precinctsSize & 0xF, PPy: precinctsSize >> 4 @@ -519,8 +527,9 @@ var JpxImage = (function JpxImageClosure() { var codeblocks = subband.codeblocks; for (var j = 0, jj = codeblocks.length; j < jj; j++) { var codeblock = codeblocks[j]; - if (codeblock.precinctNumber != precinctNumber) + if (codeblock.precinctNumber != precinctNumber) { continue; + } precinctCodeblocks.push(codeblock); } } @@ -734,17 +743,21 @@ var JpxImage = (function JpxImageClosure() { } function readCodingpasses() { var value = readBits(1); - if (value === 0) + if (value === 0) { return 1; + } value = (value << 1) | readBits(1); - if (value == 0x02) + if (value == 0x02) { return 2; + } value = (value << 2) | readBits(2); - if (value <= 0x0E) + if (value <= 0x0E) { return (value & 0x03) + 3; + } value = (value << 5) | readBits(5); - if (value <= 0x1FE) + if (value <= 0x1FE) { return (value & 0x1F) + 6; + } value = (value << 7) | readBits(7); return (value & 0x7F) + 37; } @@ -800,24 +813,28 @@ var JpxImage = (function JpxImageClosure() { } } } - if (!codeblockIncluded) + if (!codeblockIncluded) { continue; + } if (firstTimeInclusion) { zeroBitPlanesTree = precinct.zeroBitPlanesTree; zeroBitPlanesTree.reset(codeblockColumn, codeblockRow); while (true) { if (readBits(1)) { var valueReady = !zeroBitPlanesTree.nextLevel(); - if (valueReady) + if (valueReady) { break; - } else + } + } else { zeroBitPlanesTree.incrementValue(); + } } codeblock.zeroBitPlanes = zeroBitPlanesTree.value; } var codingpasses = readCodingpasses(); - while (readBits(1)) + while (readBits(1)) { codeblock.Lblock++; + } var codingpassesLog2 = log2(codingpasses); // rounding down log2 var bits = ((codingpasses < (1 << codingpassesLog2)) ? @@ -833,8 +850,9 @@ var JpxImage = (function JpxImageClosure() { while (queue.length > 0) { var packetItem = queue.shift(); var codeblock = packetItem.codeblock; - if (!('data' in codeblock)) + if (!('data' in codeblock)) { codeblock.data = []; + } codeblock.data.push({ data: data, start: offset + position, @@ -854,10 +872,12 @@ var JpxImage = (function JpxImageClosure() { var codeblock = codeblocks[i]; var blockWidth = codeblock.tbx1_ - codeblock.tbx0_; var blockHeight = codeblock.tby1_ - codeblock.tby0_; - if (blockWidth === 0 || blockHeight === 0) + if (blockWidth === 0 || blockHeight === 0) { continue; - if (!('data' in codeblock)) + } + if (!('data' in codeblock)) { continue; + } var bitModel, currentCodingpassType; bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, @@ -892,8 +912,9 @@ var JpxImage = (function JpxImageClosure() { break; case 2: bitModel.runCleanupPass(); - if (segmentationSymbolUsed) + if (segmentationSymbolUsed) { bitModel.checkSegmentationSymbol(); + } break; } currentCodingpassType = (currentCodingpassType + 1) % 3; @@ -911,8 +932,9 @@ var JpxImage = (function JpxImageClosure() { // not all bitplanes were decoded for reversible transformation n += n < 0 ? n - r : n > 0 ? n + r : 0; correction = 1 << (mb - nb); - } else + } else { correction = 1; + } coefficients[offset++] = n * correction * delta; position++; } @@ -1017,14 +1039,16 @@ var JpxImage = (function JpxImageClosure() { // Section G.1 DC level shifting to unsigned component values for (var c = 0; c < componentsCount; c++) { var component = components[c]; - if (component.isSigned) + if (component.isSigned) { continue; + } var offset = 1 << (component.precision - 1); var tileImage = result[c]; var items = tileImage.items; - for (var j = 0, jj = items.length; j < jj; j++) + for (var j = 0, jj = items.length; j < jj; j++) { items[j] += offset; + } } // To simplify things: shift and clamp output to 8 bit unsigned @@ -1129,8 +1153,9 @@ var JpxImage = (function JpxImageClosure() { this.levels = []; for (var i = 0; i < levelsLength; i++) { var items = new Uint8Array(width * height); - for (var j = 0, jj = items.length; j < jj; j++) + for (var j = 0, jj = items.length; j < jj; j++) { items[j] = defaultValue; + } var level = { width: width, @@ -1152,8 +1177,9 @@ var JpxImage = (function JpxImageClosure() { level.index = index; var value = level.items[index]; - if (value == 0xFF) + if (value == 0xFF) { break; + } if (value > stopValue) { this.currentLevel = currentLevel; @@ -1189,8 +1215,9 @@ var JpxImage = (function JpxImageClosure() { var value = level.items[level.index]; level.items[level.index] = 0xFF; currentLevel--; - if (currentLevel < 0) + if (currentLevel < 0) { return false; + } this.currentLevel = currentLevel; var level = this.levels[currentLevel]; @@ -1316,8 +1343,9 @@ var JpxImage = (function JpxImageClosure() { }, renormD: function ArithmeticDecoder_renormD() { do { - if (this.ct === 0) + if (this.ct === 0) { this.byteIn(); + } this.a <<= 1; this.chigh = ((this.chigh << 1) & 0xFFFF) | ((this.clow >> 15) & 1); @@ -1388,12 +1416,14 @@ var JpxImage = (function JpxImageClosure() { // Table D-2 function calcSignContribution(significance0, sign0, significance1, sign1) { if (significance1) { - if (!sign1) + if (!sign1) { return significance0 ? (!sign0 ? 1 : 0) : 1; - else + } else { return significance0 ? (!sign0 ? 0 : -1) : -1; - } else + } + } else { return significance0 ? (!sign0 ? 1 : -1) : 0; + } } // Table D-3 var SignContextLabels = [ @@ -1441,8 +1471,9 @@ var JpxImage = (function JpxImageClosure() { this.runLengthContext = {index: 3, mps: 0}; this.contexts = []; this.contexts.push({index: 4, mps: 0}); - for (var i = 1; i <= 16; i++) + for (var i = 1; i <= 16; i++) { this.contexts.push({index: 0, mps: 0}); + } }, setNeighborsSignificance: function BitModel_setNeighborsSignificance(row, column) { @@ -1450,23 +1481,29 @@ var JpxImage = (function JpxImageClosure() { var width = this.width, height = this.height; var index = row * width + column; if (row > 0) { - if (column > 0) + if (column > 0) { neighborsSignificance[index - width - 1] += 0x10; - if (column + 1 < width) + } + if (column + 1 < width) { neighborsSignificance[index - width + 1] += 0x10; + } neighborsSignificance[index - width] += 0x04; } if (row + 1 < height) { - if (column > 0) + if (column > 0) { neighborsSignificance[index + width - 1] += 0x10; - if (column + 1 < width) + } + if (column + 1 < width) { neighborsSignificance[index + width + 1] += 0x10; + } neighborsSignificance[index + width] += 0x04; } - if (column > 0) + if (column > 0) { neighborsSignificance[index - 1] += 0x01; - if (column + 1 < width) + } + if (column + 1 < width) { neighborsSignificance[index + 1] += 0x01; + } neighborsSignificance[index] |= 0x80; }, runSignificancePropogationPass: @@ -1485,16 +1522,18 @@ var JpxImage = (function JpxImageClosure() { var processedInverseMask = ~1; var processedMask = 1; var firstMagnitudeBitMask = 2; - for (var q = 0, qq = width * height; q < qq; q++) + for (var q = 0, qq = width * height; q < qq; q++) { processingFlags[q] &= processedInverseMask; + } for (var i0 = 0; i0 < height; i0 += 4) { for (var j = 0; j < width; j++) { var index = i0 * width + j; for (var i1 = 0; i1 < 4; i1++, index += width) { var i = i0 + i1; - if (i >= height) + if (i >= height) { break; + } if (coefficentsMagnitude[index] || !neighborsSignificance[index]) continue; @@ -1553,14 +1592,16 @@ var JpxImage = (function JpxImageClosure() { for (var j = 0; j < width; j++) { for (var i1 = 0; i1 < 4; i1++) { var i = i0 + i1; - if (i >= height) + if (i >= height) { break; + } var index = i * width + j; // significant but not those that have just become if (!coefficentsMagnitude[index] || - (processingFlags[index] & processedMask) !== 0) + (processingFlags[index] & processedMask) !== 0) { continue; + } var contextLabel = 16; if ((processingFlags[index] & @@ -1637,19 +1678,22 @@ var JpxImage = (function JpxImageClosure() { processingFlags[index] |= firstMagnitudeBitMask; index = index0; - for (var i2 = i0; i2 <= i; i2++, index += width) + for (var i2 = i0; i2 <= i; i2++, index += width) { bitsDecoded[index]++; + } i1++; } for (; i1 < 4; i1++, index += width) { i = i0 + i1; - if (i >= height) + if (i >= height) { break; + } if (coefficentsMagnitude[index] || - (processingFlags[index] & processedMask) !== 0) + (processingFlags[index] & processedMask) !== 0) { continue; + } var contextLabel = labels[neighborsSignificance[index]]; cx = contexts[contextLabel]; @@ -1671,8 +1715,9 @@ var JpxImage = (function JpxImageClosure() { var cx = this.uniformContext; var symbol = (decoder.readBit(cx) << 3) | (decoder.readBit(cx) << 2) | (decoder.readBit(cx) << 1) | decoder.readBit(cx); - if (symbol != 0xA) + if (symbol != 0xA) { throw 'Invalid segmentation symbol'; + } } };