Second stage, smasks now working. Still needs optimization.
This commit is contained in:
parent
2a632d4ab2
commit
146cd8c861
@ -1036,28 +1036,6 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
this.restore();
|
this.restore();
|
||||||
},
|
},
|
||||||
|
|
||||||
paintJpegXObject: function canvasGraphicsPaintJpegXObject(objId, w, h) {
|
|
||||||
var image = this.objs.get(objId);
|
|
||||||
debugger;
|
|
||||||
if (!image) {
|
|
||||||
error('Dependent image isn\'t ready yet');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
this.paintNormalImageXObject(image);
|
|
||||||
/*
|
|
||||||
this.save();
|
|
||||||
|
|
||||||
var ctx = this.ctx;
|
|
||||||
// scale the image to the unit square
|
|
||||||
ctx.scale(1 / w, -1 / h);
|
|
||||||
|
|
||||||
ctx.drawImage(image.data, 0, 0, image.width, image.height,
|
|
||||||
0, -h, w, h);
|
|
||||||
|
|
||||||
this.restore(); */
|
|
||||||
},
|
|
||||||
|
|
||||||
paintImageMaskXObject: function canvasGraphicsPaintImageMaskXObject(
|
paintImageMaskXObject: function canvasGraphicsPaintImageMaskXObject(
|
||||||
imgArray, inverseDecode, width, height) {
|
imgArray, inverseDecode, width, height) {
|
||||||
function applyStencilMask(buffer, inverseDecode) {
|
function applyStencilMask(buffer, inverseDecode) {
|
||||||
@ -1107,7 +1085,11 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
this.restore();
|
this.restore();
|
||||||
},
|
},
|
||||||
|
|
||||||
paintNormalImageXObject: function canvasGraphicsPaintImageXObject(imgData) {
|
paintImageXObject: function canvasGraphicsPaintImageXObject(objId) {
|
||||||
|
var imgData = this.objs.get(objId);
|
||||||
|
if (!imgData) {
|
||||||
|
error('Dependent image isn\'t ready yet');
|
||||||
|
}
|
||||||
this.save();
|
this.save();
|
||||||
var ctx = this.ctx;
|
var ctx = this.ctx;
|
||||||
var w = imgData.width;
|
var w = imgData.width;
|
||||||
@ -1137,21 +1119,6 @@ var CanvasGraphics = (function canvasGraphics() {
|
|||||||
this.restore();
|
this.restore();
|
||||||
},
|
},
|
||||||
|
|
||||||
paintImageXObject: function canvasGraphicsPaintImageXObject(type, data) {
|
|
||||||
debugger;
|
|
||||||
switch(type) {
|
|
||||||
case 'jpeg':
|
|
||||||
this.paintJpegXObject.apply(this, data);
|
|
||||||
break;
|
|
||||||
case 'imageMask':
|
|
||||||
this.paintImageMaskXObject.apply(this, data);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.paintNormalImageXObject.apply(this, data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// Marked content
|
// Marked content
|
||||||
|
|
||||||
markPoint: function canvasGraphicsMarkPoint(tag) {
|
markPoint: function canvasGraphicsMarkPoint(tag) {
|
||||||
|
27
src/core.js
27
src/core.js
@ -560,7 +560,7 @@ var PDFDoc = (function pdfDoc() {
|
|||||||
var type = data[1];
|
var type = data[1];
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'Jpeg':
|
case 'Image':
|
||||||
var imageData = data[2];
|
var imageData = data[2];
|
||||||
this.objs.resolve(id, imageData);
|
this.objs.resolve(id, imageData);
|
||||||
break;
|
break;
|
||||||
@ -610,21 +610,32 @@ var PDFDoc = (function pdfDoc() {
|
|||||||
|
|
||||||
messageHandler.on('jpeg_decode', function(message) {
|
messageHandler.on('jpeg_decode', function(message) {
|
||||||
var imageData = message.data[0];
|
var imageData = message.data[0];
|
||||||
|
var components = message.data[1];
|
||||||
|
if (components != 3 && components != 1)
|
||||||
|
error('Only 3 component or 1 component can be returned');
|
||||||
|
|
||||||
var img = new Image();
|
var img = new Image();
|
||||||
img.onload = (function jpegImageLoaderOnload() {
|
img.onload = (function jpegImageLoaderOnload() {
|
||||||
var width = img.width;
|
var width = img.width;
|
||||||
var height = img.height;
|
var height = img.height;
|
||||||
var length = width * height * 4;
|
var size = width * height;
|
||||||
var buf = new Uint8Array(length);
|
var rgbaLength = size * 4;
|
||||||
|
var buf = new Uint8Array(size * components);
|
||||||
var tempCanvas = new ScratchCanvas(width, height);
|
var tempCanvas = new ScratchCanvas(width, height);
|
||||||
var tempCtx = tempCanvas.getContext('2d');
|
var tempCtx = tempCanvas.getContext('2d');
|
||||||
tempCtx.drawImage(img, 0, 0);
|
tempCtx.drawImage(img, 0, 0);
|
||||||
var data = tempCtx.getImageData(0, 0, width, height).data;
|
var data = tempCtx.getImageData(0, 0, width, height).data;
|
||||||
for (var i = 0; i < length; i += 4) {
|
|
||||||
buf[i] = data[i];
|
if (components == 3) {
|
||||||
buf[i + 1] = data[i + 1];
|
for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
|
||||||
buf[i + 2] = data[i + 2];
|
buf[j] = data[i];
|
||||||
buf[i + 3] = data[i + 3];
|
buf[j + 1] = data[i + 1];
|
||||||
|
buf[j + 2] = data[i + 2];
|
||||||
|
}
|
||||||
|
} else if(components == 1) {
|
||||||
|
for (var i = 0, j = 0; i < rgbaLength; i += 4, j++) {
|
||||||
|
buf[j] = data[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
message.resolve({ data: buf, width: width, height: height});
|
message.resolve({ data: buf, width: width, height: height});
|
||||||
}).bind(this);
|
}).bind(this);
|
||||||
|
@ -183,38 +183,42 @@ var PartialEvaluator = (function partialEvaluator() {
|
|||||||
var dict = image.dict;
|
var dict = image.dict;
|
||||||
var w = dict.get('Width', 'W');
|
var w = dict.get('Width', 'W');
|
||||||
var h = dict.get('Height', 'H');
|
var h = dict.get('Height', 'H');
|
||||||
fn = 'paintImageXObject';
|
|
||||||
|
|
||||||
if (image instanceof JpegStream && image.isNative) {
|
var imageMask = dict.get('ImageMask', 'IM') || false;
|
||||||
var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
|
if (imageMask) {
|
||||||
debugger;
|
// This depends on a tmpCanvas beeing filled with the
|
||||||
handler.send('jpeg_decode', [image.getIR()], function(data) {
|
// current fillStyle, such that processing the pixel
|
||||||
handler.send('obj', [objId, 'Jpeg', data]);
|
// data can't be done here. Instead of creating a
|
||||||
});
|
// complete PDFImage, only read the information needed
|
||||||
|
// for later.
|
||||||
|
|
||||||
// Add the dependency on the image object.
|
var width = dict.get('Width', 'W');
|
||||||
insertDependency([objId]);
|
var height = dict.get('Height', 'H');
|
||||||
|
var bitStrideLength = (width + 7) >> 3;
|
||||||
// The normal fn.
|
var imgArray = image.getBytes(bitStrideLength * height);
|
||||||
args = ['jpeg', [objId, w, h]];
|
var decode = dict.get('Decode', 'D');
|
||||||
|
var inverseDecode = !!decode && decode[0] > 0;
|
||||||
|
|
||||||
|
fn = 'paintImageMaskXObject';
|
||||||
|
args = [imgArray, inverseDecode, width, height];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needs to be rendered ourself.
|
|
||||||
|
|
||||||
// Figure out if the image has an imageMask.
|
|
||||||
var imageMask = dict.get('ImageMask', 'IM') || false;
|
|
||||||
|
|
||||||
// If there is no imageMask, create the PDFImage and a lot
|
// If there is no imageMask, create the PDFImage and a lot
|
||||||
// of image processing can be done here.
|
// of image processing can be done here.
|
||||||
if (!imageMask) {
|
var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
|
||||||
var imageObj = new PDFImage(xref, resources, image, inline);
|
insertDependency([objId]);
|
||||||
|
fn = 'paintImageXObject';
|
||||||
|
args = [objId, w, h];
|
||||||
|
var resolve = (function(objId) {
|
||||||
|
return function resolve(data) {
|
||||||
|
handler.send('obj', [objId, 'Image', data]);
|
||||||
|
};
|
||||||
|
})(objId);
|
||||||
|
|
||||||
if (imageObj.imageMask) {
|
var imageObj = new PDFImage(xref, resources, image, inline, handler);
|
||||||
throw 'Can\'t handle this in the web worker :/';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
imageObj.ready(function() {
|
||||||
var imgData = {
|
var imgData = {
|
||||||
width: w,
|
width: w,
|
||||||
height: h,
|
height: h,
|
||||||
@ -222,25 +226,8 @@ var PartialEvaluator = (function partialEvaluator() {
|
|||||||
};
|
};
|
||||||
var pixels = imgData.data;
|
var pixels = imgData.data;
|
||||||
imageObj.fillRgbaBuffer(pixels, imageObj.decode);
|
imageObj.fillRgbaBuffer(pixels, imageObj.decode);
|
||||||
|
resolve(imgData);
|
||||||
args = ['normal', [imgData]];
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This depends on a tmpCanvas beeing filled with the
|
|
||||||
// current fillStyle, such that processing the pixel
|
|
||||||
// data can't be done here. Instead of creating a
|
|
||||||
// complete PDFImage, only read the information needed
|
|
||||||
// for later.
|
|
||||||
|
|
||||||
var width = dict.get('Width', 'W');
|
|
||||||
var height = dict.get('Height', 'H');
|
|
||||||
var bitStrideLength = (width + 7) >> 3;
|
|
||||||
var imgArray = image.getBytes(bitStrideLength * height);
|
|
||||||
var decode = dict.get('Decode', 'D');
|
|
||||||
var inverseDecode = !!decode && decode[0] > 0;
|
|
||||||
|
|
||||||
args = ['imageMask', [imgArray, inverseDecode, width, height]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uniquePrefix = uniquePrefix || '';
|
uniquePrefix = uniquePrefix || '';
|
||||||
|
50
src/image.js
50
src/image.js
@ -4,8 +4,12 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
var PDFImage = (function pdfImage() {
|
var PDFImage = (function pdfImage() {
|
||||||
function constructor(xref, res, image, inline) {
|
function constructor(xref, res, image, inline, handler) {
|
||||||
this.image = image;
|
this.image = image;
|
||||||
|
this.imageReady = true;
|
||||||
|
this.smaskReady = true;
|
||||||
|
this.callbacks = [];
|
||||||
|
|
||||||
if (image.getParams) {
|
if (image.getParams) {
|
||||||
// JPX/JPEG2000 streams directly contain bits per component
|
// JPX/JPEG2000 streams directly contain bits per component
|
||||||
// and color space mode information.
|
// and color space mode information.
|
||||||
@ -56,7 +60,24 @@ var PDFImage = (function pdfImage() {
|
|||||||
if (mask) {
|
if (mask) {
|
||||||
TODO('masked images');
|
TODO('masked images');
|
||||||
} else if (smask) {
|
} else if (smask) {
|
||||||
this.smask = new PDFImage(xref, res, smask);
|
this.smaskReady = false;
|
||||||
|
this.smask = new PDFImage(xref, res, smask, false, handler);
|
||||||
|
this.smask.ready(function() {
|
||||||
|
this.smaskReady = true;
|
||||||
|
if (this.isReady())
|
||||||
|
this.fireReady();
|
||||||
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (image instanceof JpegStream && image.isNative) {
|
||||||
|
this.imageReady = false;
|
||||||
|
handler.send('jpeg_decode', [image.getIR(), this.numComps], function(message) {
|
||||||
|
var data = message.data;
|
||||||
|
this.image = new Stream(data, 0, data.length);
|
||||||
|
this.imageReady = true;
|
||||||
|
if (this.isReady())
|
||||||
|
this.fireReady();
|
||||||
|
}.bind(this));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,18 +151,6 @@ var PDFImage = (function pdfImage() {
|
|||||||
var buf = new Uint8Array(width * height);
|
var buf = new Uint8Array(width * height);
|
||||||
|
|
||||||
if (smask) {
|
if (smask) {
|
||||||
if (smask.image.getImage) {
|
|
||||||
// smask is a DOM image
|
|
||||||
var tempCanvas = new ScratchCanvas(width, height);
|
|
||||||
var tempCtx = tempCanvas.getContext('2d');
|
|
||||||
var domImage = smask.image.getImage();
|
|
||||||
tempCtx.drawImage(domImage, 0, 0, domImage.width, domImage.height,
|
|
||||||
0, 0, width, height);
|
|
||||||
var data = tempCtx.getImageData(0, 0, width, height).data;
|
|
||||||
for (var i = 0, j = 0, ii = width * height; i < ii; ++i, j += 4)
|
|
||||||
buf[i] = data[j]; // getting first component value
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
var sw = smask.width;
|
var sw = smask.width;
|
||||||
var sh = smask.height;
|
var sh = smask.height;
|
||||||
if (sw != this.width || sh != this.height)
|
if (sw != this.width || sh != this.height)
|
||||||
@ -224,6 +233,19 @@ var PDFImage = (function pdfImage() {
|
|||||||
|
|
||||||
for (var i = 0; i < length; ++i)
|
for (var i = 0; i < length; ++i)
|
||||||
buffer[i] = comps[i];
|
buffer[i] = comps[i];
|
||||||
|
},
|
||||||
|
isReady: function isReady() {
|
||||||
|
return this.imageReady && this.smaskReady;
|
||||||
|
},
|
||||||
|
fireReady: function fireReady() {
|
||||||
|
for (var i = 0; i < this.callbacks.length; ++i) {
|
||||||
|
this.callbacks[i]();
|
||||||
|
this.callbacks = [];
|
||||||
|
},
|
||||||
|
ready: function ready(callback) {
|
||||||
|
this.callbacks.push(callback);
|
||||||
|
if (this.isReady())
|
||||||
|
this.fireReady();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return constructor;
|
return constructor;
|
||||||
|
Loading…
Reference in New Issue
Block a user