Respect the 'ColorTransform' entry in the image dictionary when decoding JPEG images (bug 956965, issue 6574)
Fixes https://bugzilla.mozilla.org/show_bug.cgi?id=956965. Fixes 6574.
This commit is contained in:
parent
6c263c1994
commit
116ba19dd9
@ -146,18 +146,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
|||||||
*/
|
*/
|
||||||
NativeImageDecoder.isSupported =
|
NativeImageDecoder.isSupported =
|
||||||
function NativeImageDecoder_isSupported(image, xref, res) {
|
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') &&
|
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.
|
* Checks if the image can be decoded by the browser.
|
||||||
*/
|
*/
|
||||||
NativeImageDecoder.isDecodable =
|
NativeImageDecoder.isDecodable =
|
||||||
function NativeImageDecoder_isDecodable(image, xref, res) {
|
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) &&
|
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,
|
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)
|
* (partners.adobe.com/public/developer/en/ps/sdk/5116.DCT_Filter.pdf)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var JpegImage = (function jpegImage() {
|
var JpegImage = (function JpegImageClosure() {
|
||||||
var dctZigZag = new Uint8Array([
|
var dctZigZag = new Uint8Array([
|
||||||
0,
|
0,
|
||||||
1, 8,
|
1, 8,
|
||||||
@ -68,7 +68,9 @@ var JpegImage = (function jpegImage() {
|
|||||||
var dctSqrt2 = 5793; // sqrt(2)
|
var dctSqrt2 = 5793; // sqrt(2)
|
||||||
var dctSqrt1d2 = 2896; // sqrt(2) / 2
|
var dctSqrt1d2 = 2896; // sqrt(2) / 2
|
||||||
|
|
||||||
function constructor() {
|
function JpegImage() {
|
||||||
|
this.decodeTransform = null;
|
||||||
|
this.colorTransform = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildHuffmanTable(codeLengths, values) {
|
function buildHuffmanTable(codeLengths, values) {
|
||||||
@ -585,7 +587,7 @@ var JpegImage = (function jpegImage() {
|
|||||||
return a <= 0 ? 0 : a >= 255 ? 255 : a;
|
return a <= 0 ? 0 : a >= 255 ? 255 : a;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor.prototype = {
|
JpegImage.prototype = {
|
||||||
parse: function parse(data) {
|
parse: function parse(data) {
|
||||||
|
|
||||||
function readUint16() {
|
function readUint16() {
|
||||||
@ -902,8 +904,20 @@ var JpegImage = (function jpegImage() {
|
|||||||
// The adobe transform marker overrides any previous setting
|
// The adobe transform marker overrides any previous setting
|
||||||
return true;
|
return true;
|
||||||
} else if (this.numComponents === 3) {
|
} 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;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -1045,7 +1059,7 @@ var JpegImage = (function jpegImage() {
|
|||||||
rgbData[offset++] = grayColor;
|
rgbData[offset++] = grayColor;
|
||||||
}
|
}
|
||||||
return rgbData;
|
return rgbData;
|
||||||
} else if (this.numComponents === 3) {
|
} else if (this.numComponents === 3 && this._isColorConversionNeeded()) {
|
||||||
return this._convertYccToRgb(data);
|
return this._convertYccToRgb(data);
|
||||||
} else if (this.numComponents === 4) {
|
} else if (this.numComponents === 4) {
|
||||||
if (this._isColorConversionNeeded()) {
|
if (this._isColorConversionNeeded()) {
|
||||||
@ -1062,7 +1076,7 @@ var JpegImage = (function jpegImage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return constructor;
|
return JpegImage;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
exports.JpegImage = JpegImage;
|
exports.JpegImage = JpegImage;
|
||||||
|
@ -596,7 +596,7 @@ var Parser = (function ParserClosure() {
|
|||||||
}
|
}
|
||||||
if (name === 'DCTDecode' || name === 'DCT') {
|
if (name === 'DCTDecode' || name === 'DCT') {
|
||||||
xrefStreamStats[StreamType.DCT] = true;
|
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') {
|
if (name === 'JPXDecode' || name === 'JPX') {
|
||||||
xrefStreamStats[StreamType.JPX] = true;
|
xrefStreamStats[StreamType.JPX] = true;
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
var Util = sharedUtil.Util;
|
var Util = sharedUtil.Util;
|
||||||
var error = sharedUtil.error;
|
var error = sharedUtil.error;
|
||||||
var info = sharedUtil.info;
|
var info = sharedUtil.info;
|
||||||
|
var isInt = sharedUtil.isInt;
|
||||||
var isArray = sharedUtil.isArray;
|
var isArray = sharedUtil.isArray;
|
||||||
var createObjectURL = sharedUtil.createObjectURL;
|
var createObjectURL = sharedUtil.createObjectURL;
|
||||||
var shadow = sharedUtil.shadow;
|
var shadow = sharedUtil.shadow;
|
||||||
@ -891,7 +892,7 @@ var PredictorStream = (function PredictorStreamClosure() {
|
|||||||
* DecodeStreams.
|
* DecodeStreams.
|
||||||
*/
|
*/
|
||||||
var JpegStream = (function JpegStreamClosure() {
|
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.
|
// Some images may contain 'junk' before the SOI (start-of-image) marker.
|
||||||
// Note: this seems to mainly affect inline images.
|
// Note: this seems to mainly affect inline images.
|
||||||
var ch;
|
var ch;
|
||||||
@ -925,8 +926,8 @@ var JpegStream = (function JpegStreamClosure() {
|
|||||||
var jpegImage = new JpegImage();
|
var jpegImage = new JpegImage();
|
||||||
|
|
||||||
// Checking if values need to be transformed before conversion.
|
// 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', 'D');
|
||||||
var decodeArr = this.dict.getArray('Decode');
|
if (this.forceRGB && isArray(decodeArr)) {
|
||||||
var bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
|
var bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
|
||||||
var decodeArrLength = decodeArr.length;
|
var decodeArrLength = decodeArr.length;
|
||||||
var transform = new Int32Array(decodeArrLength);
|
var transform = new Int32Array(decodeArrLength);
|
||||||
@ -943,6 +944,14 @@ var JpegStream = (function JpegStreamClosure() {
|
|||||||
jpegImage.decodeTransform = transform;
|
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);
|
jpegImage.parse(this.bytes);
|
||||||
var data = jpegImage.getData(this.drawWidth, this.drawHeight,
|
var data = jpegImage.getData(this.drawWidth, this.drawHeight,
|
||||||
@ -1064,7 +1073,7 @@ var Jbig2Stream = (function Jbig2StreamClosure() {
|
|||||||
var jbig2Image = new Jbig2Image();
|
var jbig2Image = new Jbig2Image();
|
||||||
|
|
||||||
var chunks = [];
|
var chunks = [];
|
||||||
var decodeParams = this.dict.getArray('DecodeParms');
|
var decodeParams = this.dict.getArray('DecodeParms', 'DP');
|
||||||
|
|
||||||
// According to the PDF specification, DecodeParms can be either
|
// According to the PDF specification, DecodeParms can be either
|
||||||
// a dictionary, or an array whose elements are dictionaries.
|
// 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,
|
"lastPage": 1,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "bug956965",
|
||||||
|
"file": "pdfs/bug956965.pdf",
|
||||||
|
"md5": "9b2f1176c797ee84e989a507e745f89d",
|
||||||
|
"rounds": 1,
|
||||||
|
"link": true,
|
||||||
|
"firstPage": 33,
|
||||||
|
"lastPage": 33,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "smaskdim",
|
{ "id": "smaskdim",
|
||||||
"file": "pdfs/smaskdim.pdf",
|
"file": "pdfs/smaskdim.pdf",
|
||||||
"md5": "de80aeca7cbf79940189fd34d59671ee",
|
"md5": "de80aeca7cbf79940189fd34d59671ee",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user