Merge pull request #4939 from yurydelendik/issue3591

Fixes JPX COC support / JPX error reporting refactoring
This commit is contained in:
Yury Delendik 2014-06-13 18:52:36 -05:00
commit 834c69aa0a
3 changed files with 80 additions and 51 deletions

View File

@ -14,7 +14,7 @@
* 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.
*/ */
/* globals ArithmeticDecoder, error, globalScope, log2, readUint16, readUint32, /* globals ArithmeticDecoder, globalScope, log2, readUint16, readUint32,
warn */ warn */
'use strict'; 'use strict';
@ -58,7 +58,7 @@ var JpxImage = (function JpxImageClosure() {
lbox = length - position + headerSize; lbox = length - position + headerSize;
} }
if (lbox < headerSize) { if (lbox < headerSize) {
error('JPX error: Invalid box field size'); throw new Error('JPX Error: Invalid box field size');
} }
var dataLength = lbox - headerSize; var dataLength = lbox - headerSize;
var jumpDataLength = true; var jumpDataLength = true;
@ -82,41 +82,34 @@ var JpxImage = (function JpxImageClosure() {
} }
}, },
parseImageProperties: function JpxImage_parseImageProperties(stream) { parseImageProperties: function JpxImage_parseImageProperties(stream) {
try { var newByte = stream.getByte();
var newByte = stream.getByte(); while (newByte >= 0) {
while (newByte >= 0) { var oldByte = newByte;
var oldByte = newByte; newByte = stream.getByte();
newByte = stream.getByte(); var code = (oldByte << 8) | newByte;
var code = (oldByte << 8) | newByte; // Image and tile size (SIZ)
// Image and tile size (SIZ) if (code == 0xFF51) {
if (code == 0xFF51) { stream.skip(4);
stream.skip(4); var Xsiz = stream.getInt32() >>> 0; // Byte 4
var Xsiz = stream.getInt32() >>> 0; // Byte 4 var Ysiz = stream.getInt32() >>> 0; // Byte 8
var Ysiz = stream.getInt32() >>> 0; // Byte 8 var XOsiz = stream.getInt32() >>> 0; // Byte 12
var XOsiz = stream.getInt32() >>> 0; // Byte 12 var YOsiz = stream.getInt32() >>> 0; // Byte 16
var YOsiz = stream.getInt32() >>> 0; // Byte 16 stream.skip(16);
stream.skip(16); var Csiz = stream.getUint16(); // Byte 36
var Csiz = stream.getUint16(); // Byte 36 this.width = Xsiz - XOsiz;
this.width = Xsiz - XOsiz; this.height = Ysiz - YOsiz;
this.height = Ysiz - YOsiz; this.componentsCount = Csiz;
this.componentsCount = Csiz; // Results are always returned as Uint8Arrays
// Results are always returned as Uint8Arrays this.bitsPerComponent = 8;
this.bitsPerComponent = 8; return;
return;
}
}
throw 'No size marker found in JPX stream';
} catch (e) {
if (this.failOnCorruptedImage) {
error('JPX error: ' + e);
} else {
warn('JPX error: ' + e + '. Trying to recover');
} }
} }
throw new Error('JPX Error: No size marker found in JPX stream');
}, },
parseCodestream: function JpxImage_parseCodestream(data, start, end) { parseCodestream: function JpxImage_parseCodestream(data, start, end) {
var context = {}; var context = {};
try { try {
var doNotRecover = false;
var position = start; var position = start;
while (position + 1 < end) { while (position + 1 < end) {
var code = readUint16(data, position); var code = readUint16(data, position);
@ -160,6 +153,11 @@ var JpxImage = (function JpxImageClosure() {
context.QCC = []; context.QCC = [];
context.COC = []; context.COC = [];
break; break;
case 0xFF55: // Tile-part lengths, main header (TLM)
var Ltlm = readUint16(data, position); // Marker segment length
// Skip tile length markers
position += Ltlm;
break;
case 0xFF5C: // Quantization default (QCD) case 0xFF5C: // Quantization default (QCD)
length = readUint16(data, position); length = readUint16(data, position);
var qcd = {}; var qcd = {};
@ -179,7 +177,7 @@ var JpxImage = (function JpxImageClosure() {
scalarExpounded = true; scalarExpounded = true;
break; break;
default: default:
throw 'Invalid SQcd value ' + sqcd; throw new Error('JPX Error: Invalid SQcd value ' + sqcd);
} }
qcd.noQuantization = (spqcdSize == 8); qcd.noQuantization = (spqcdSize == 8);
qcd.scalarExpounded = scalarExpounded; qcd.scalarExpounded = scalarExpounded;
@ -231,7 +229,7 @@ var JpxImage = (function JpxImageClosure() {
scalarExpounded = true; scalarExpounded = true;
break; break;
default: default:
throw 'Invalid SQcd value ' + sqcd; throw new Error('JPX Error: Invalid SQcd value ' + sqcd);
} }
qcc.noQuantization = (spqcdSize == 8); qcc.noQuantization = (spqcdSize == 8);
qcc.scalarExpounded = scalarExpounded; qcc.scalarExpounded = scalarExpounded;
@ -291,16 +289,33 @@ var JpxImage = (function JpxImageClosure() {
} }
cod.precinctsSizes = precinctsSizes; cod.precinctsSizes = precinctsSizes;
} }
var unsupported = [];
if (cod.sopMarkerUsed || cod.ephMarkerUsed || if (cod.sopMarkerUsed) {
cod.selectiveArithmeticCodingBypass || unsupported.push('sopMarkerUsed');
cod.resetContextProbabilities || }
cod.terminationOnEachCodingPass || if (cod.ephMarkerUsed) {
cod.verticalyStripe || cod.predictableTermination) { unsupported.push('ephMarkerUsed');
throw 'Unsupported COD options: ' + }
globalScope.JSON.stringify(cod); if (cod.selectiveArithmeticCodingBypass) {
unsupported.push('selectiveArithmeticCodingBypass');
}
if (cod.resetContextProbabilities) {
unsupported.push('resetContextProbabilities');
}
if (cod.terminationOnEachCodingPass) {
unsupported.push('terminationOnEachCodingPass');
}
if (cod.verticalyStripe) {
unsupported.push('verticalyStripe');
}
if (cod.predictableTermination) {
unsupported.push('predictableTermination');
}
if (unsupported.length > 0) {
doNotRecover = true;
throw new Error('JPX Error: Unsupported COD options (' +
unsupported.join(', ') + ')');
} }
if (context.mainHeader) { if (context.mainHeader) {
context.COD = cod; context.COD = cod;
} else { } else {
@ -343,17 +358,19 @@ var JpxImage = (function JpxImageClosure() {
// skipping content // skipping content
break; break;
case 0xFF53: // Coding style component (COC) case 0xFF53: // Coding style component (COC)
throw 'Codestream code 0xFF53 (COC) is not implemented'; throw new Error('JPX Error: Codestream code 0xFF53 (COC) is ' +
'not implemented');
default: default:
throw 'Unknown codestream code: ' + code.toString(16); throw new Error('JPX Error: Unknown codestream code: ' +
code.toString(16));
} }
position += length; position += length;
} }
} catch (e) { } catch (e) {
if (this.failOnCorruptedImage) { if (doNotRecover || this.failOnCorruptedImage) {
error('JPX error: ' + e); throw e;
} else { } else {
warn('JPX error: ' + e + '. Trying to recover'); warn('Trying to recover from ' + e.message);
} }
} }
this.tiles = transformComponents(context); this.tiles = transformComponents(context);
@ -581,7 +598,7 @@ var JpxImage = (function JpxImageClosure() {
} }
r = 0; r = 0;
} }
throw 'Out of packets'; throw new Error('JPX Error: Out of packets');
}; };
} }
function ResolutionLayerComponentPositionIterator(context) { function ResolutionLayerComponentPositionIterator(context) {
@ -621,7 +638,7 @@ var JpxImage = (function JpxImageClosure() {
} }
l = 0; l = 0;
} }
throw 'Out of packets'; throw new Error('JPX Error: Out of packets');
}; };
} }
function buildPackets(context) { function buildPackets(context) {
@ -716,7 +733,8 @@ var JpxImage = (function JpxImageClosure() {
new ResolutionLayerComponentPositionIterator(context); new ResolutionLayerComponentPositionIterator(context);
break; break;
default: default:
throw 'Unsupported progression order ' + progressionOrder; throw new Error('JPX Error: Unsupported progression order ' +
progressionOrder);
} }
} }
function parseTilePackets(context, data, offset, dataLength) { function parseTilePackets(context, data, offset, dataLength) {
@ -1629,7 +1647,7 @@ var JpxImage = (function JpxImageClosure() {
(decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) | (decoder.readBit(contexts, UNIFORM_CONTEXT) << 1) |
decoder.readBit(contexts, UNIFORM_CONTEXT); decoder.readBit(contexts, UNIFORM_CONTEXT);
if (symbol != 0xA) { if (symbol != 0xA) {
throw 'Invalid segmentation symbol'; throw new Error('JPX Error: Invalid segmentation symbol');
} }
} }
}; };

View File

@ -0,0 +1 @@
http://web.archive.org/web/20130425084432/http://harpers.org/wp-content/uploads/HarpersMagazine-1989-09-0059029.pdf

View File

@ -1507,6 +1507,16 @@
"rounds": 1, "rounds": 1,
"type": "eq" "type": "eq"
}, },
{ "id": "issue3591",
"file": "pdfs/issue3591.pdf",
"md5": "f76b3e9d1a44621b73063cf10556c6ff",
"link": true,
"firstPage": 1,
"lastPage": 1,
"rounds": 1,
"type": "eq",
"about": "JPX with 0xFF55 marker"
},
{ "id": "bug766138", { "id": "bug766138",
"file": "pdfs/bug766138.pdf", "file": "pdfs/bug766138.pdf",
"md5": "b171f5cf8d9834348112fba60ee54f8c", "md5": "b171f5cf8d9834348112fba60ee54f8c",