Browse Source

Scale smask and image to the max dimensions of either one. Fix grayscale to scale the input value based on bpc.

Brendan Dahl 14 years ago
parent
commit
87d72023dc
  1. 8
      src/evaluator.js
  2. 63
      src/image.js

8
src/evaluator.js

@ -222,12 +222,12 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
PDFImage.buildImage(function(imageObj) { PDFImage.buildImage(function(imageObj) {
var imgData = { var imgData = {
width: w, width: imageObj.maxWidth,
height: h, height: imageObj.maxHeight,
data: new Uint8Array(w * h * 4) data: new Uint8Array(imageObj.maxWidth * imageObj.maxHeight * 4)
}; };
var pixels = imgData.data; var pixels = imgData.data;
imageObj.fillRgbaBuffer(pixels); imageObj.fillRgbaBuffer(pixels, imageObj.maxWidth, imageObj.maxHeight);
handler.send('obj', [objId, 'Image', imgData]); handler.send('obj', [objId, 'Image', imgData]);
}, handler, xref, resources, image, inline); }, handler, xref, resources, image, inline);
} }

63
src/image.js

@ -131,28 +131,52 @@ var PDFImage = (function PDFImageClosure() {
* Resize an image using the nearest neighbor algorithm. Currently only * Resize an image using the nearest neighbor algorithm. Currently only
* supports one component images. * supports one component images.
* @param {TypedArray} pixels The original image with one component. * @param {TypedArray} pixels The original image with one component.
* @param {Number} bpc Number of bits per component.
* @param {Number} components Number of color components, 1 or 3 is supported.
* @param {Number} w1 Original width. * @param {Number} w1 Original width.
* @param {Number} h1 Original height. * @param {Number} h1 Original height.
* @param {Number} w2 New width. * @param {Number} w2 New width.
* @param {Number} h2 New height. * @param {Number} h2 New height.
* @return {TypedArray} Resized image data. * @return {TypedArray} Resized image data.
*/ */
PDFImage.resize = function resize(pixels, w1, h1, w2, h2) { PDFImage.resize = function resize(pixels, bpc, components, w1, h1, w2, h2) {
var temp = new Uint8Array(w2 * h2); var length = w2 * h2 * components;
var temp = bpc <= 8 ? new Uint8Array(length) :
bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
var xRatio = w1 / w2; var xRatio = w1 / w2;
var yRatio = h1 / h2; var yRatio = h1 / h2;
var px, py; var px, py, newIndex, oldIndex;
for (var i = 0; i < h2; i++) { for (var i = 0; i < h2; i++) {
for (var j = 0; j < w2; j++) { for (var j = 0; j < w2; j++) {
px = Math.floor(j * xRatio); px = Math.floor(j * xRatio);
py = Math.floor(i * yRatio); py = Math.floor(i * yRatio);
temp[(i * w2) + j] = pixels[((py * w1) + px)]; newIndex = (i * w2) + j;
oldIndex = ((py * w1) + px);
if (components === 1) {
temp[newIndex] = pixels[oldIndex];
} else if(components === 3) {
newIndex *= 3;
oldIndex *= 3;
temp[newIndex] = pixels[oldIndex];
temp[newIndex + 1] = pixels[oldIndex + 1];
temp[newIndex + 2] = pixels[oldIndex + 2];
}
} }
} }
return temp; return temp;
}; };
PDFImage.prototype = { PDFImage.prototype = {
get maxWidth() {
if (!this.smask)
return this.width;
return Math.max(this.width, this.smask.width);
},
get maxHeight() {
if (!this.smask)
return this.height;
return Math.max(this.height, this.smask.height);
},
getComponents: function getComponents(buffer) { getComponents: function getComponents(buffer) {
var bpc = this.bpc; var bpc = this.bpc;
var needsDecode = this.needsDecode; var needsDecode = this.needsDecode;
@ -241,10 +265,10 @@ var PDFImage = (function PDFImageClosure() {
} }
return output; return output;
}, },
getOpacity: function getOpacity() { getOpacity: function getOpacity(width, height) {
var smask = this.smask; var smask = this.smask;
var width = this.width; var originalWidth = this.width;
var height = this.height; var originalHeight = this.height;
var buf; var buf;
if (smask) { if (smask) {
@ -252,9 +276,8 @@ var PDFImage = (function PDFImageClosure() {
var sh = smask.height; var sh = smask.height;
buf = new Uint8Array(sw * sh); buf = new Uint8Array(sw * sh);
smask.fillGrayBuffer(buf); smask.fillGrayBuffer(buf);
if (sw != this.width || sh != this.height) if (sw != width || sh != height)
buf = PDFImage.resize(buf, sw, sh, this.width, this.height); buf = PDFImage.resize(buf, smask.bps, 1, sw, sh, width, height);
return buf;
} else { } else {
buf = new Uint8Array(width * height); buf = new Uint8Array(width * height);
for (var i = 0, ii = width * height; i < ii; ++i) for (var i = 0, ii = width * height; i < ii; ++i)
@ -285,20 +308,23 @@ var PDFImage = (function PDFImageClosure() {
} }
} }
}, },
fillRgbaBuffer: function fillRgbaBuffer(buffer) { fillRgbaBuffer: function fillRgbaBuffer(buffer, width, height) {
var numComps = this.numComps; var numComps = this.numComps;
var width = this.width; var originalWidth = this.width;
var height = this.height; var originalHeight = this.height;
var bpc = this.bpc; var bpc = this.bpc;
// rows start at byte boundary; // rows start at byte boundary;
var rowBytes = (width * numComps * bpc + 7) >> 3; var rowBytes = (originalWidth * numComps * bpc + 7) >> 3;
var imgArray = this.getImageBytes(height * rowBytes); var imgArray = this.getImageBytes(originalHeight * rowBytes);
var comps = this.colorSpace.getRgbBuffer( var comps = this.colorSpace.getRgbBuffer(
this.getComponents(imgArray), bpc); this.getComponents(imgArray), bpc);
if (originalWidth != width || originalHeight != height)
comps = PDFImage.resize(comps, this.bpc, 3, originalWidth, originalHeight,
width, height);
var compsPos = 0; var compsPos = 0;
var opacity = this.getOpacity(); var opacity = this.getOpacity(width, height);
var opacityPos = 0; var opacityPos = 0;
var length = width * height * 4; var length = width * height * 4;
@ -324,9 +350,10 @@ var PDFImage = (function PDFImageClosure() {
var comps = this.getComponents(imgArray); var comps = this.getComponents(imgArray);
var length = width * height; var length = width * height;
// we aren't using a colorspace so we need to scale the value
var scale = 255 / ((1 << bpc) - 1);
for (var i = 0; i < length; ++i) for (var i = 0; i < length; ++i)
buffer[i] = comps[i]; buffer[i] = (scale * comps[i]) | 0;
}, },
getImageBytes: function getImageBytes(length) { getImageBytes: function getImageBytes(length) {
this.image.reset(); this.image.reset();

Loading…
Cancel
Save