Merge pull request #4939 from yurydelendik/issue3591
Fixes JPX COC support / JPX error reporting refactoring
This commit is contained in:
commit
834c69aa0a
120
src/core/jpx.js
120
src/core/jpx.js
@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
1
test/pdfs/issue3591.pdf.link
Normal file
1
test/pdfs/issue3591.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
http://web.archive.org/web/20130425084432/http://harpers.org/wp-content/uploads/HarpersMagazine-1989-09-0059029.pdf
|
@ -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",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user