Second stage, smasks now working. Still needs optimization.

This commit is contained in:
Brendan Dahl 2011-12-08 12:50:34 -08:00
parent 2a632d4ab2
commit 146cd8c861
4 changed files with 88 additions and 101 deletions

View File

@ -1036,28 +1036,6 @@ var CanvasGraphics = (function canvasGraphics() {
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(
imgArray, inverseDecode, width, height) {
function applyStencilMask(buffer, inverseDecode) {
@ -1107,7 +1085,11 @@ var CanvasGraphics = (function canvasGraphics() {
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();
var ctx = this.ctx;
var w = imgData.width;
@ -1137,21 +1119,6 @@ var CanvasGraphics = (function canvasGraphics() {
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
markPoint: function canvasGraphicsMarkPoint(tag) {

View File

@ -560,7 +560,7 @@ var PDFDoc = (function pdfDoc() {
var type = data[1];
switch (type) {
case 'Jpeg':
case 'Image':
var imageData = data[2];
this.objs.resolve(id, imageData);
break;
@ -610,21 +610,32 @@ var PDFDoc = (function pdfDoc() {
messageHandler.on('jpeg_decode', function(message) {
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();
img.onload = (function jpegImageLoaderOnload() {
var width = img.width;
var height = img.height;
var length = width * height * 4;
var buf = new Uint8Array(length);
var size = width * height;
var rgbaLength = size * 4;
var buf = new Uint8Array(size * components);
var tempCanvas = new ScratchCanvas(width, height);
var tempCtx = tempCanvas.getContext('2d');
tempCtx.drawImage(img, 0, 0);
var data = tempCtx.getImageData(0, 0, width, height).data;
for (var i = 0; i < length; i += 4) {
buf[i] = data[i];
buf[i + 1] = data[i + 1];
buf[i + 2] = data[i + 2];
buf[i + 3] = data[i + 3];
if (components == 3) {
for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
buf[j] = data[i];
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});
}).bind(this);

View File

@ -183,38 +183,42 @@ var PartialEvaluator = (function partialEvaluator() {
var dict = image.dict;
var w = dict.get('Width', 'W');
var h = dict.get('Height', 'H');
fn = 'paintImageXObject';
if (image instanceof JpegStream && image.isNative) {
var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
debugger;
handler.send('jpeg_decode', [image.getIR()], function(data) {
handler.send('obj', [objId, 'Jpeg', data]);
});
var imageMask = dict.get('ImageMask', 'IM') || false;
if (imageMask) {
// 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.
// Add the dependency on the image object.
insertDependency([objId]);
// The normal fn.
args = ['jpeg', [objId, w, h]];
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;
fn = 'paintImageMaskXObject';
args = [imgArray, inverseDecode, width, height];
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
// of image processing can be done here.
if (!imageMask) {
var imageObj = new PDFImage(xref, resources, image, inline);
var objId = 'img_' + uniquePrefix + (++self.objIdCounter);
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) {
throw 'Can\'t handle this in the web worker :/';
}
var imageObj = new PDFImage(xref, resources, image, inline, handler);
imageObj.ready(function() {
var imgData = {
width: w,
height: h,
@ -222,25 +226,8 @@ var PartialEvaluator = (function partialEvaluator() {
};
var pixels = imgData.data;
imageObj.fillRgbaBuffer(pixels, imageObj.decode);
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]];
resolve(imgData);
});
}
uniquePrefix = uniquePrefix || '';

View File

@ -4,8 +4,12 @@
'use strict';
var PDFImage = (function pdfImage() {
function constructor(xref, res, image, inline) {
function constructor(xref, res, image, inline, handler) {
this.image = image;
this.imageReady = true;
this.smaskReady = true;
this.callbacks = [];
if (image.getParams) {
// JPX/JPEG2000 streams directly contain bits per component
// and color space mode information.
@ -56,7 +60,24 @@ var PDFImage = (function pdfImage() {
if (mask) {
TODO('masked images');
} 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);
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 sh = smask.height;
if (sw != this.width || sh != this.height)
@ -224,6 +233,19 @@ var PDFImage = (function pdfImage() {
for (var i = 0; i < length; ++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;