|
|
|
@ -49,7 +49,7 @@ var PDFImage = (function PDFImageClosure() {
@@ -49,7 +49,7 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
// Clamp the value to the range
|
|
|
|
|
return value < 0 ? 0 : value > max ? max : value; |
|
|
|
|
} |
|
|
|
|
function PDFImage(xref, res, image, inline, smask, mask) { |
|
|
|
|
function PDFImage(xref, res, image, inline, smask, mask, isMask) { |
|
|
|
|
this.image = image; |
|
|
|
|
if (image.getParams) { |
|
|
|
|
// JPX/JPEG2000 streams directly contain bits per component
|
|
|
|
@ -95,8 +95,9 @@ var PDFImage = (function PDFImageClosure() {
@@ -95,8 +95,9 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
|
|
|
|
|
this.decode = dict.get('Decode', 'D'); |
|
|
|
|
this.needsDecode = false; |
|
|
|
|
if (this.decode && this.colorSpace && |
|
|
|
|
!this.colorSpace.isDefaultDecode(this.decode)) { |
|
|
|
|
if (this.decode && |
|
|
|
|
((this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode)) || |
|
|
|
|
(isMask && !ColorSpace.isDefaultDecode(this.decode, 1)))) { |
|
|
|
|
this.needsDecode = true; |
|
|
|
|
// Do some preprocessing to avoid more math.
|
|
|
|
|
var max = (1 << bitsPerComponent) - 1; |
|
|
|
@ -114,7 +115,7 @@ var PDFImage = (function PDFImageClosure() {
@@ -114,7 +115,7 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
this.smask = new PDFImage(xref, res, smask, false); |
|
|
|
|
} else if (mask) { |
|
|
|
|
if (isStream(mask)) { |
|
|
|
|
this.mask = new PDFImage(xref, res, mask, false); |
|
|
|
|
this.mask = new PDFImage(xref, res, mask, false, null, null, true); |
|
|
|
|
} else { |
|
|
|
|
// Color key mask (just an array).
|
|
|
|
|
this.mask = mask; |
|
|
|
@ -216,13 +217,37 @@ var PDFImage = (function PDFImageClosure() {
@@ -216,13 +217,37 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
return this.height; |
|
|
|
|
return Math.max(this.height, this.smask.height); |
|
|
|
|
}, |
|
|
|
|
getComponents: function PDFImage_getComponents(buffer) { |
|
|
|
|
decodeBuffer: function PDFImage_decodeBuffer(buffer) { |
|
|
|
|
var bpc = this.bpc; |
|
|
|
|
var needsDecode = this.needsDecode; |
|
|
|
|
var decodeMap = this.decode; |
|
|
|
|
var numComps = this.numComps; |
|
|
|
|
|
|
|
|
|
var decodeAddends, decodeCoefficients; |
|
|
|
|
var decodeAddends = this.decodeAddends; |
|
|
|
|
var decodeCoefficients = this.decodeCoefficients; |
|
|
|
|
var max = (1 << bpc) - 1; |
|
|
|
|
|
|
|
|
|
if (bpc === 1) { |
|
|
|
|
// If the buffer needed decode that means it just needs to be inverted.
|
|
|
|
|
for (var i = 0, ii = buffer.length; i < ii; i++) { |
|
|
|
|
buffer[i] = +!(buffer[i]); |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
var index = 0; |
|
|
|
|
for (var i = 0, ii = this.width * this.height; i < ii; i++) { |
|
|
|
|
for (var j = 0; j < numComps; j++) { |
|
|
|
|
buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], |
|
|
|
|
decodeCoefficients[j], max); |
|
|
|
|
index++; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
getComponents: function PDFImage_getComponents(buffer) { |
|
|
|
|
var bpc = this.bpc; |
|
|
|
|
|
|
|
|
|
// This image doesn't require any extra work.
|
|
|
|
|
if (bpc == 8 && !needsDecode) |
|
|
|
|
if (bpc === 8) |
|
|
|
|
return buffer; |
|
|
|
|
|
|
|
|
|
var bufferLength = buffer.length; |
|
|
|
@ -235,29 +260,11 @@ var PDFImage = (function PDFImageClosure() {
@@ -235,29 +260,11 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
var output = bpc <= 8 ? new Uint8Array(length) : |
|
|
|
|
bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length); |
|
|
|
|
var rowComps = width * numComps; |
|
|
|
|
var decodeAddends, decodeCoefficients; |
|
|
|
|
if (needsDecode) { |
|
|
|
|
decodeAddends = this.decodeAddends; |
|
|
|
|
decodeCoefficients = this.decodeCoefficients; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var max = (1 << bpc) - 1; |
|
|
|
|
|
|
|
|
|
if (bpc == 8) { |
|
|
|
|
// Optimization for reading 8 bpc images that have a decode.
|
|
|
|
|
for (var i = 0, ii = length; i < ii; ++i) { |
|
|
|
|
var compIndex = i % numComps; |
|
|
|
|
var value = buffer[i]; |
|
|
|
|
value = decodeAndClamp(value, decodeAddends[compIndex], |
|
|
|
|
decodeCoefficients[compIndex], max); |
|
|
|
|
output[i] = value; |
|
|
|
|
} |
|
|
|
|
} else if (bpc == 1) { |
|
|
|
|
if (bpc === 1) { |
|
|
|
|
// Optimization for reading 1 bpc images.
|
|
|
|
|
var valueZero = 0, valueOne = 1; |
|
|
|
|
if (decodeMap) { |
|
|
|
|
valueZero = decodeMap[0] ? 1 : 0; |
|
|
|
|
valueOne = decodeMap[1] ? 1 : 0; |
|
|
|
|
} |
|
|
|
|
var mask = 0; |
|
|
|
|
var buf = 0; |
|
|
|
|
|
|
|
|
@ -274,7 +281,7 @@ var PDFImage = (function PDFImageClosure() {
@@ -274,7 +281,7 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
mask = 128; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
output[i] = !(buf & mask) ? valueZero : valueOne; |
|
|
|
|
output[i] = +!!(buf & mask); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
// The general case that handles all other bpc values.
|
|
|
|
@ -292,12 +299,7 @@ var PDFImage = (function PDFImageClosure() {
@@ -292,12 +299,7 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
|
|
|
|
|
var remainingBits = bits - bpc; |
|
|
|
|
var value = buf >> remainingBits; |
|
|
|
|
if (needsDecode) { |
|
|
|
|
var compIndex = i % numComps; |
|
|
|
|
value = decodeAndClamp(value, decodeAddends[compIndex], |
|
|
|
|
decodeCoefficients[compIndex], max); |
|
|
|
|
} |
|
|
|
|
output[i] = value; |
|
|
|
|
output[i] = value < 0 ? 0 : value > max ? max : value; |
|
|
|
|
buf = buf & ((1 << remainingBits) - 1); |
|
|
|
|
bits = remainingBits; |
|
|
|
|
} |
|
|
|
@ -397,21 +399,27 @@ var PDFImage = (function PDFImageClosure() {
@@ -397,21 +399,27 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
// imgArray can be incomplete (e.g. after CCITT fax encoding)
|
|
|
|
|
var actualHeight = 0 | (imgArray.length / rowBytes * |
|
|
|
|
height / originalHeight); |
|
|
|
|
var comps = this.getComponents(imgArray); |
|
|
|
|
// Build opacity here since color key masking needs to be perormed on
|
|
|
|
|
// undecoded values.
|
|
|
|
|
var opacity = this.getOpacity(width, height, comps); |
|
|
|
|
|
|
|
|
|
var comps = this.colorSpace.createRgbBuffer(this.getComponents(imgArray), |
|
|
|
|
0, originalWidth * originalHeight, bpc); |
|
|
|
|
if (this.needsDecode) { |
|
|
|
|
this.decodeBuffer(comps); |
|
|
|
|
} |
|
|
|
|
var rgbBuf = this.colorSpace.createRgbBuffer(comps, 0, |
|
|
|
|
originalWidth * originalHeight, bpc); |
|
|
|
|
if (originalWidth != width || originalHeight != height) |
|
|
|
|
comps = PDFImage.resize(comps, this.bpc, 3, originalWidth, |
|
|
|
|
rgbBuf = PDFImage.resize(rgbBuf, this.bpc, 3, originalWidth, |
|
|
|
|
originalHeight, width, height); |
|
|
|
|
var compsPos = 0; |
|
|
|
|
var opacity = this.getOpacity(width, height, imgArray); |
|
|
|
|
var opacityPos = 0; |
|
|
|
|
var length = width * actualHeight * 4; |
|
|
|
|
|
|
|
|
|
for (var i = 0; i < length; i += 4) { |
|
|
|
|
buffer[i] = comps[compsPos++]; |
|
|
|
|
buffer[i + 1] = comps[compsPos++]; |
|
|
|
|
buffer[i + 2] = comps[compsPos++]; |
|
|
|
|
buffer[i] = rgbBuf[compsPos++]; |
|
|
|
|
buffer[i + 1] = rgbBuf[compsPos++]; |
|
|
|
|
buffer[i + 2] = rgbBuf[compsPos++]; |
|
|
|
|
buffer[i + 3] = opacity[opacityPos++]; |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
@ -429,6 +437,9 @@ var PDFImage = (function PDFImageClosure() {
@@ -429,6 +437,9 @@ var PDFImage = (function PDFImageClosure() {
|
|
|
|
|
var imgArray = this.getImageBytes(height * rowBytes); |
|
|
|
|
|
|
|
|
|
var comps = this.getComponents(imgArray); |
|
|
|
|
if (this.needsDecode) { |
|
|
|
|
this.decodeBuffer(comps); |
|
|
|
|
} |
|
|
|
|
var length = width * height; |
|
|
|
|
// we aren't using a colorspace so we need to scale the value
|
|
|
|
|
var scale = 255 / ((1 << bpc) - 1); |
|
|
|
|