Merge pull request #7661 from Snuffleupagus/bug-956965

Respect the 'ColorTransform' entry in the image dictionary when decoding JPEG images (bug 956965, issue 6574)
This commit is contained in:
Tim van der Meij 2016-09-27 20:22:43 +02:00 committed by GitHub
commit 7f381c8064
6 changed files with 56 additions and 15 deletions

View File

@ -146,18 +146,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
*/
NativeImageDecoder.isSupported =
function NativeImageDecoder_isSupported(image, xref, res) {
var cs = ColorSpace.parse(image.dict.get('ColorSpace', 'CS'), xref, res);
var dict = image.dict;
if (dict.has('DecodeParms') || dict.has('DP')) {
return false;
}
var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res);
return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') &&
cs.isDefaultDecode(image.dict.getArray('Decode', 'D'));
cs.isDefaultDecode(dict.getArray('Decode', 'D'));
};
/**
* Checks if the image can be decoded by the browser.
*/
NativeImageDecoder.isDecodable =
function NativeImageDecoder_isDecodable(image, xref, res) {
var cs = ColorSpace.parse(image.dict.get('ColorSpace', 'CS'), xref, res);
var dict = image.dict;
if (dict.has('DecodeParms') || dict.has('DP')) {
return false;
}
var cs = ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res);
return (cs.numComps === 1 || cs.numComps === 3) &&
cs.isDefaultDecode(image.dict.getArray('Decode', 'D'));
cs.isDefaultDecode(dict.getArray('Decode', 'D'));
};
function PartialEvaluator(pdfManager, xref, handler, pageIndex,

View File

@ -40,7 +40,7 @@ var error = sharedUtil.error;
* (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
*/
var JpegImage = (function jpegImage() {
var JpegImage = (function JpegImageClosure() {
var dctZigZag = new Uint8Array([
0,
1, 8,
@ -68,7 +68,9 @@ var JpegImage = (function jpegImage() {
var dctSqrt2 = 5793; // sqrt(2)
var dctSqrt1d2 = 2896; // sqrt(2) / 2
function constructor() {
function JpegImage() {
this.decodeTransform = null;
this.colorTransform = -1;
}
function buildHuffmanTable(codeLengths, values) {
@ -585,7 +587,7 @@ var JpegImage = (function jpegImage() {
return a <= 0 ? 0 : a >= 255 ? 255 : a;
}
constructor.prototype = {
JpegImage.prototype = {
parse: function parse(data) {
function readUint16() {
@ -902,8 +904,20 @@ var JpegImage = (function jpegImage() {
// The adobe transform marker overrides any previous setting
return true;
} else if (this.numComponents === 3) {
if (!this.adobe && this.colorTransform === 0) {
// If the Adobe transform marker is not present and the image
// dictionary has a 'ColorTransform' entry, explicitly set to `0`,
// then the colours should *not* be transformed.
return false;
}
return true;
} else {
} else { // `this.numComponents !== 3`
if (!this.adobe && this.colorTransform === 1) {
// If the Adobe transform marker is not present and the image
// dictionary has a 'ColorTransform' entry, explicitly set to `1`,
// then the colours should be transformed.
return true;
}
return false;
}
},
@ -1045,7 +1059,7 @@ var JpegImage = (function jpegImage() {
rgbData[offset++] = grayColor;
}
return rgbData;
} else if (this.numComponents === 3) {
} else if (this.numComponents === 3 && this._isColorConversionNeeded()) {
return this._convertYccToRgb(data);
} else if (this.numComponents === 4) {
if (this._isColorConversionNeeded()) {
@ -1062,7 +1076,7 @@ var JpegImage = (function jpegImage() {
}
};
return constructor;
return JpegImage;
})();
exports.JpegImage = JpegImage;

View File

@ -596,7 +596,7 @@ var Parser = (function ParserClosure() {
}
if (name === 'DCTDecode' || name === 'DCT') {
xrefStreamStats[StreamType.DCT] = true;
return new JpegStream(stream, maybeLength, stream.dict, this.xref);
return new JpegStream(stream, maybeLength, stream.dict);
}
if (name === 'JPXDecode' || name === 'JPX') {
xrefStreamStats[StreamType.JPX] = true;

View File

@ -34,6 +34,7 @@
var Util = sharedUtil.Util;
var error = sharedUtil.error;
var info = sharedUtil.info;
var isInt = sharedUtil.isInt;
var isArray = sharedUtil.isArray;
var createObjectURL = sharedUtil.createObjectURL;
var shadow = sharedUtil.shadow;
@ -891,7 +892,7 @@ var PredictorStream = (function PredictorStreamClosure() {
* DecodeStreams.
*/
var JpegStream = (function JpegStreamClosure() {
function JpegStream(stream, maybeLength, dict, xref) {
function JpegStream(stream, maybeLength, dict) {
// Some images may contain 'junk' before the SOI (start-of-image) marker.
// Note: this seems to mainly affect inline images.
var ch;
@ -925,8 +926,8 @@ var JpegStream = (function JpegStreamClosure() {
var jpegImage = new JpegImage();
// Checking if values need to be transformed before conversion.
if (this.forceRGB && this.dict && isArray(this.dict.get('Decode'))) {
var decodeArr = this.dict.getArray('Decode');
var decodeArr = this.dict.getArray('Decode', 'D');
if (this.forceRGB && isArray(decodeArr)) {
var bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
var decodeArrLength = decodeArr.length;
var transform = new Int32Array(decodeArrLength);
@ -943,6 +944,14 @@ var JpegStream = (function JpegStreamClosure() {
jpegImage.decodeTransform = transform;
}
}
// Fetching the 'ColorTransform' entry, if it exists.
var decodeParams = this.dict.get('DecodeParms', 'DP');
if (isDict(decodeParams)) {
var colorTransform = decodeParams.get('ColorTransform');
if (isInt(colorTransform)) {
jpegImage.colorTransform = colorTransform;
}
}
jpegImage.parse(this.bytes);
var data = jpegImage.getData(this.drawWidth, this.drawHeight,
@ -1064,7 +1073,7 @@ var Jbig2Stream = (function Jbig2StreamClosure() {
var jbig2Image = new Jbig2Image();
var chunks = [];
var decodeParams = this.dict.getArray('DecodeParms');
var decodeParams = this.dict.getArray('DecodeParms', 'DP');
// According to the PDF specification, DecodeParms can be either
// a dictionary, or an array whose elements are dictionaries.

View File

@ -0,0 +1 @@
http://web.archive.org/web/20160414174617/http://cache.lego.com/bigdownloads/buildinginstructions/6030672.pdf

View File

@ -1156,6 +1156,15 @@
"lastPage": 1,
"type": "eq"
},
{ "id": "bug956965",
"file": "pdfs/bug956965.pdf",
"md5": "9b2f1176c797ee84e989a507e745f89d",
"rounds": 1,
"link": true,
"firstPage": 33,
"lastPage": 33,
"type": "eq"
},
{ "id": "smaskdim",
"file": "pdfs/smaskdim.pdf",
"md5": "de80aeca7cbf79940189fd34d59671ee",