From 19fa6a5260444d5da0f5888357f70a4215fe6d95 Mon Sep 17 00:00:00 2001 From: Brendan Dahl Date: Tue, 28 Aug 2012 17:19:31 -0700 Subject: [PATCH] Adds support for color key mask. --- src/image.js | 64 ++++++++++++++++++++++++++----------- test/pdfs/colorkeymask.pdf | Bin 0 -> 161533 bytes test/test_manifest.json | 6 ++++ 3 files changed, 52 insertions(+), 18 deletions(-) create mode 100644 test/pdfs/colorkeymask.pdf diff --git a/src/image.js b/src/image.js index 59f70f99a..907607ebe 100644 --- a/src/image.js +++ b/src/image.js @@ -97,7 +97,12 @@ var PDFImage = (function PDFImageClosure() { if (smask) { this.smask = new PDFImage(xref, res, smask, false); } else if (mask) { - this.mask = new PDFImage(xref, res, mask, false); + if (isStream(mask)) { + this.mask = new PDFImage(xref, res, mask, false); + } else { + // Color key mask (just an array). + this.mask = mask; + } } } /** @@ -129,11 +134,15 @@ var PDFImage = (function PDFImageClosure() { maskPromise.resolve(null); } else { smaskPromise.resolve(null); - if (mask && isStream(mask)) { - handleImageData(handler, xref, res, mask, maskPromise); - } else if (mask) { - TODO('handle color key masking'); - maskPromise.resolve(null); + if (mask) { + if (isStream(mask)) { + handleImageData(handler, xref, res, mask, maskPromise); + } else if (isArray(mask)) { + maskPromise.resolve(mask); + } else { + warn('Unsupported mask format.'); + maskPromise.resolve(null); + } } else { maskPromise.resolve(null); } @@ -279,7 +288,7 @@ var PDFImage = (function PDFImageClosure() { } return output; }, - getOpacity: function PDFImage_getOpacity(width, height) { + getOpacity: function PDFImage_getOpacity(width, height, image) { var smask = this.smask; var mask = this.mask; var originalWidth = this.width; @@ -294,18 +303,37 @@ var PDFImage = (function PDFImageClosure() { if (sw != width || sh != height) buf = PDFImage.resize(buf, smask.bpc, 1, sw, sh, width, height); } else if (mask) { - var sw = mask.width; - var sh = mask.height; - buf = new Uint8Array(sw * sh); - mask.numComps = 1; - mask.fillGrayBuffer(buf); + if (mask instanceof PDFImage) { + var sw = mask.width; + var sh = mask.height; + buf = new Uint8Array(sw * sh); + mask.numComps = 1; + mask.fillGrayBuffer(buf); - // Need to invert values in buffer - for (var i = 0, ii = sw * sh; i < ii; ++i) - buf[i] = 255 - buf[i]; + // Need to invert values in buffer + for (var i = 0, ii = sw * sh; i < ii; ++i) + buf[i] = 255 - buf[i]; - if (sw != width || sh != height) - buf = PDFImage.resize(buf, mask.bpc, 1, sw, sh, width, height); + if (sw != width || sh != height) + buf = PDFImage.resize(buf, mask.bpc, 1, sw, sh, width, height); + } else if (isArray(mask)) { + // Color key mask: if any of the compontents are outside the range + // then they should be painted. + buf = new Uint8Array(width * height); + for (var i = 0, ii = width * height; i < ii; ++i) { + var opacity = 0; + for (var j = 0; j < this.numComps; ++j) { + var color = image[i * this.numComps + j]; + if (color < mask[j * 2] || color > mask[j * 2 + 1]) { + opacity = 255; + break; + } + } + buf[i] = opacity; + } + } else { + error('Unknown mask format.'); + } } else { buf = new Uint8Array(width * height); for (var i = 0, ii = width * height; i < ii; ++i) @@ -357,7 +385,7 @@ var PDFImage = (function PDFImageClosure() { comps = PDFImage.resize(comps, this.bpc, 3, originalWidth, originalHeight, width, height); var compsPos = 0; - var opacity = this.getOpacity(width, height); + var opacity = this.getOpacity(width, height, imgArray); var opacityPos = 0; var length = width * actualHeight * 4; diff --git a/test/pdfs/colorkeymask.pdf b/test/pdfs/colorkeymask.pdf new file mode 100644 index 0000000000000000000000000000000000000000..a056d9cbc63587ec39f82705b9cf4040e719cef4 GIT binary patch literal 161533 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