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:
commit
7f381c8064
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
1
test/pdfs/bug956965.pdf.link
Normal file
1
test/pdfs/bug956965.pdf.link
Normal file
@ -0,0 +1 @@
|
||||
http://web.archive.org/web/20160414174617/http://cache.lego.com/bigdownloads/buildinginstructions/6030672.pdf
|
@ -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",
|
||||
|
Loading…
x
Reference in New Issue
Block a user