Fallback to the built-in JPEG decoder if 'JpegStream', in src/display/api.js
, fails to load the image
This works by making `PartialEvaluator.buildPaintImageXObject` wait for the success/failure of `loadJpegStream` on the API side *before* parsing continues. Please note that in practice, it should be quite rare for the browser to fail loading/decoding of a JPEG image. In the general case, it should thus not be completely surprising if even `src/core/jpg.js` will fail to decode the image.
This commit is contained in:
parent
76afe1018b
commit
80441346a3
@ -349,7 +349,8 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
},
|
},
|
||||||
|
|
||||||
buildPaintImageXObject({ resources, image, isInline = false, operatorList,
|
buildPaintImageXObject({ resources, image, isInline = false, operatorList,
|
||||||
cacheKey, imageCache, }) {
|
cacheKey, imageCache,
|
||||||
|
forceDisableNativeImageDecoder = false, }) {
|
||||||
var dict = image.dict;
|
var dict = image.dict;
|
||||||
var w = dict.get('Width', 'W');
|
var w = dict.get('Width', 'W');
|
||||||
var h = dict.get('Height', 'H');
|
var h = dict.get('Height', 'H');
|
||||||
@ -419,28 +420,47 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
var nativeImageDecoderSupport = this.options.nativeImageDecoderSupport;
|
const nativeImageDecoderSupport = forceDisableNativeImageDecoder ?
|
||||||
|
NativeImageDecoding.NONE : this.options.nativeImageDecoderSupport;
|
||||||
// If there is no imageMask, create the PDFImage and a lot
|
// If there is no imageMask, create the PDFImage and a lot
|
||||||
// of image processing can be done here.
|
// of image processing can be done here.
|
||||||
var objId = 'img_' + this.idFactory.createObjId();
|
var objId = 'img_' + this.idFactory.createObjId();
|
||||||
operatorList.addDependency(objId);
|
|
||||||
args = [objId, w, h];
|
|
||||||
|
|
||||||
if (nativeImageDecoderSupport !== NativeImageDecoding.NONE &&
|
if (nativeImageDecoderSupport !== NativeImageDecoding.NONE &&
|
||||||
!softMask && !mask && image instanceof JpegStream &&
|
!softMask && !mask && image instanceof JpegStream &&
|
||||||
NativeImageDecoder.isSupported(image, this.xref, resources,
|
NativeImageDecoder.isSupported(image, this.xref, resources,
|
||||||
this.pdfFunctionFactory)) {
|
this.pdfFunctionFactory)) {
|
||||||
// These JPEGs don't need any more processing so we can just send it.
|
// These JPEGs don't need any more processing so we can just send it.
|
||||||
operatorList.addOp(OPS.paintJpegXObject, args);
|
return this.handler.sendWithPromise('obj', [
|
||||||
this.handler.send('obj', [objId, this.pageIndex, 'JpegStream',
|
objId, this.pageIndex, 'JpegStream',
|
||||||
image.getIR(this.options.forceDataSchema)]);
|
image.getIR(this.options.forceDataSchema)
|
||||||
if (cacheKey) {
|
]).then(function() {
|
||||||
imageCache[cacheKey] = {
|
// Only add the dependency once we know that the native JPEG decoding
|
||||||
fn: OPS.paintJpegXObject,
|
// succeeded, to ensure that rendering will always complete.
|
||||||
args,
|
operatorList.addDependency(objId);
|
||||||
};
|
args = [objId, w, h];
|
||||||
}
|
|
||||||
return Promise.resolve();
|
operatorList.addOp(OPS.paintJpegXObject, args);
|
||||||
|
if (cacheKey) {
|
||||||
|
imageCache[cacheKey] = {
|
||||||
|
fn: OPS.paintJpegXObject,
|
||||||
|
args,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, (reason) => {
|
||||||
|
warn('Native JPEG decoding failed -- trying to recover: ' +
|
||||||
|
(reason && reason.message));
|
||||||
|
// Try to decode the JPEG image with the built-in decoder instead.
|
||||||
|
return this.buildPaintImageXObject({
|
||||||
|
resources,
|
||||||
|
image,
|
||||||
|
isInline,
|
||||||
|
operatorList,
|
||||||
|
cacheKey,
|
||||||
|
imageCache,
|
||||||
|
forceDisableNativeImageDecoder: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates native image decoder only if a JPEG image or mask is present.
|
// Creates native image decoder only if a JPEG image or mask is present.
|
||||||
@ -457,6 +477,10 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure that the dependency is added before the image is decoded.
|
||||||
|
operatorList.addDependency(objId);
|
||||||
|
args = [objId, w, h];
|
||||||
|
|
||||||
PDFImage.buildImage({
|
PDFImage.buildImage({
|
||||||
handler: this.handler,
|
handler: this.handler,
|
||||||
xref: this.xref,
|
xref: this.xref,
|
||||||
|
@ -1817,22 +1817,22 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
|||||||
switch (type) {
|
switch (type) {
|
||||||
case 'JpegStream':
|
case 'JpegStream':
|
||||||
imageData = data[3];
|
imageData = data[3];
|
||||||
new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.onload = function() {
|
img.onload = function() {
|
||||||
resolve(img);
|
resolve(img);
|
||||||
};
|
};
|
||||||
img.onerror = function() {
|
img.onerror = function() {
|
||||||
reject(new Error('Error during JPEG image loading'));
|
reject(new Error('Error during JPEG image loading'));
|
||||||
|
// Note that when the browser image loading/decoding fails,
|
||||||
|
// we'll fallback to the built-in PDF.js JPEG decoder; see
|
||||||
|
// `PartialEvaluator.buildPaintImageXObject` in the
|
||||||
|
// `src/core/evaluator.js` file.
|
||||||
};
|
};
|
||||||
img.src = imageData;
|
img.src = imageData;
|
||||||
}).then((img) => {
|
}).then((img) => {
|
||||||
pageProxy.objs.resolve(id, img);
|
pageProxy.objs.resolve(id, img);
|
||||||
}, (reason) => {
|
|
||||||
warn(reason);
|
|
||||||
pageProxy.objs.resolve(id, null);
|
|
||||||
});
|
});
|
||||||
break;
|
|
||||||
case 'Image':
|
case 'Image':
|
||||||
imageData = data[3];
|
imageData = data[3];
|
||||||
pageProxy.objs.resolve(id, imageData);
|
pageProxy.objs.resolve(id, imageData);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user