Rescale regular images manually if they are too big.
This commit is contained in:
parent
bcbc21a51c
commit
39038b7377
148
src/canvas.js
148
src/canvas.js
@ -224,6 +224,60 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rescaleImage(pixels, width, height, widthScale, heightScale) {
|
||||||
|
var scaledWidth = Math.ceil(width / widthScale);
|
||||||
|
var scaledHeight = Math.ceil(height / heightScale);
|
||||||
|
|
||||||
|
var itemsSum = new Float32Array(scaledWidth * scaledHeight * 3);
|
||||||
|
var itemsCount = new Float32Array(scaledWidth * scaledHeight);
|
||||||
|
var maxAlphas = new Uint8Array(scaledWidth * scaledHeight);
|
||||||
|
for (var i = 0, position = 0; i < height; i++) {
|
||||||
|
var lineOffset = (0 | (i / heightScale)) * scaledWidth;
|
||||||
|
for (var j = 0; j < width; j++) {
|
||||||
|
var countOffset = lineOffset + (0 | (j / widthScale));
|
||||||
|
var sumOffset = countOffset * 3;
|
||||||
|
var maxAlpha = maxAlphas[countOffset];
|
||||||
|
var currentAlpha = pixels[position + 3];
|
||||||
|
if (maxAlpha < currentAlpha) {
|
||||||
|
// lowering total alpha
|
||||||
|
var scale = 1 - (currentAlpha - maxAlpha) / 255;
|
||||||
|
itemsSum[sumOffset] *= scale;
|
||||||
|
itemsSum[sumOffset + 1] *= scale;
|
||||||
|
itemsSum[sumOffset + 2] *= scale;
|
||||||
|
maxAlphas[countOffset] = maxAlpha = currentAlpha;
|
||||||
|
}
|
||||||
|
if (maxAlpha > currentAlpha) {
|
||||||
|
var scale = 1 - (maxAlpha - currentAlpha) / 255;
|
||||||
|
itemsSum[sumOffset] += pixels[position] * scale;
|
||||||
|
itemsSum[sumOffset + 1] += pixels[position + 1] * scale;
|
||||||
|
itemsSum[sumOffset + 2] += pixels[position + 2] * scale;
|
||||||
|
itemsCount[countOffset] += scale;
|
||||||
|
} else {
|
||||||
|
itemsSum[sumOffset] += pixels[position];
|
||||||
|
itemsSum[sumOffset + 1] += pixels[position + 1];
|
||||||
|
itemsSum[sumOffset + 2] += pixels[position + 2];
|
||||||
|
itemsCount[countOffset]++;
|
||||||
|
}
|
||||||
|
position += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var tmpCanvas = createScratchCanvas(scaledWidth, scaledHeight);
|
||||||
|
var tmpCtx = tmpCanvas.getContext('2d');
|
||||||
|
var imgData = tmpCtx.getImageData(0, 0, scaledWidth, scaledHeight);
|
||||||
|
pixels = imgData.data;
|
||||||
|
var j = 0, q = 0;
|
||||||
|
for (var i = 0, ii = scaledWidth * scaledHeight; i < ii; i++) {
|
||||||
|
var count = itemsCount[i];
|
||||||
|
pixels[j] = itemsSum[q++] / count;
|
||||||
|
pixels[j + 1] = itemsSum[q++] / count;
|
||||||
|
pixels[j + 2] = itemsSum[q++] / count;
|
||||||
|
pixels[j + 3] = maxAlphas[i];
|
||||||
|
j += 4;
|
||||||
|
}
|
||||||
|
tmpCtx.putImageData(imgData, 0, 0);
|
||||||
|
return tmpCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
var LINE_CAP_STYLES = ['butt', 'round', 'square'];
|
var LINE_CAP_STYLES = ['butt', 'round', 'square'];
|
||||||
var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
|
var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
|
||||||
var NORMAL_CLIP = {};
|
var NORMAL_CLIP = {};
|
||||||
@ -1175,47 +1229,8 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function rescaleImage(pixels, widthScale, heightScale) {
|
|
||||||
var scaledWidth = Math.ceil(width / widthScale);
|
|
||||||
var scaledHeight = Math.ceil(height / heightScale);
|
|
||||||
|
|
||||||
var itemsSum = new Uint32Array(scaledWidth * scaledHeight * 4);
|
|
||||||
var itemsCount = new Uint32Array(scaledWidth * scaledHeight);
|
|
||||||
for (var i = 0, position = 0; i < height; i++) {
|
|
||||||
var lineOffset = (0 | (i / heightScale)) * scaledWidth;
|
|
||||||
for (var j = 0; j < width; j++) {
|
|
||||||
var countOffset = lineOffset + (0 | (j / widthScale));
|
|
||||||
var sumOffset = countOffset << 2;
|
|
||||||
itemsSum[sumOffset] += pixels[position];
|
|
||||||
itemsSum[sumOffset + 1] += pixels[position + 1];
|
|
||||||
itemsSum[sumOffset + 2] += pixels[position + 2];
|
|
||||||
itemsSum[sumOffset + 3] += pixels[position + 3];
|
|
||||||
itemsCount[countOffset]++;
|
|
||||||
position += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var tmpCanvas = createScratchCanvas(scaledWidth, scaledHeight);
|
|
||||||
var tmpCtx = tmpCanvas.getContext('2d');
|
|
||||||
var imgData = tmpCtx.getImageData(0, 0, scaledWidth, scaledHeight);
|
|
||||||
pixels = imgData.data;
|
|
||||||
for (var i = 0, j = 0, ii = scaledWidth * scaledHeight; i < ii; i++) {
|
|
||||||
var count = itemsCount[i];
|
|
||||||
pixels[j] = itemsSum[j] / count;
|
|
||||||
pixels[j + 1] = itemsSum[j + 1] / count;
|
|
||||||
pixels[j + 2] = itemsSum[j + 2] / count;
|
|
||||||
pixels[j + 3] = itemsSum[j + 3] / count;
|
|
||||||
j += 4;
|
|
||||||
}
|
|
||||||
tmpCtx.putImageData(imgData, 0, 0);
|
|
||||||
return tmpCanvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.save();
|
|
||||||
|
|
||||||
var ctx = this.ctx;
|
|
||||||
var w = width, h = height;
|
var w = width, h = height;
|
||||||
// scale the image to the unit square
|
|
||||||
ctx.scale(1 / w, -1 / h);
|
|
||||||
|
|
||||||
var tmpCanvas = createScratchCanvas(w, h);
|
var tmpCanvas = createScratchCanvas(w, h);
|
||||||
var tmpCtx = tmpCanvas.getContext('2d');
|
var tmpCtx = tmpCanvas.getContext('2d');
|
||||||
@ -1231,20 +1246,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
|
|
||||||
applyStencilMask(pixels, inverseDecode);
|
applyStencilMask(pixels, inverseDecode);
|
||||||
|
|
||||||
var currentTransform = ctx.mozCurrentTransformInverse;
|
this.paintImage(imgData);
|
||||||
var widthScale = Math.max(Math.abs(currentTransform[0]), 1);
|
|
||||||
var heightScale = Math.max(Math.abs(currentTransform[3]), 1);
|
|
||||||
if (widthScale >= 2 || heightScale >= 2) {
|
|
||||||
// canvas does not resize well large images to small -- using simple
|
|
||||||
// algorithm to perform pre-scaling
|
|
||||||
tmpCanvas = rescaleImage(imgData.data, widthScale, heightScale);
|
|
||||||
ctx.scale(widthScale, heightScale);
|
|
||||||
ctx.drawImage(tmpCanvas, 0, -h / heightScale);
|
|
||||||
} else {
|
|
||||||
tmpCtx.putImageData(imgData, 0, 0);
|
|
||||||
ctx.drawImage(tmpCanvas, 0, -h);
|
|
||||||
}
|
|
||||||
this.restore();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
|
paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
|
||||||
@ -1252,23 +1254,45 @@ var CanvasGraphics = (function CanvasGraphicsClosure() {
|
|||||||
if (!imgData)
|
if (!imgData)
|
||||||
error('Dependent image isn\'t ready yet');
|
error('Dependent image isn\'t ready yet');
|
||||||
|
|
||||||
this.save();
|
this.paintImage(imgData);
|
||||||
|
},
|
||||||
|
|
||||||
|
paintImage: function CanvasGraphics_paintImage(imgData) {
|
||||||
|
var width = imgData.width;
|
||||||
|
var height = imgData.height;
|
||||||
var ctx = this.ctx;
|
var ctx = this.ctx;
|
||||||
var w = imgData.width;
|
this.save();
|
||||||
var h = imgData.height;
|
|
||||||
// scale the image to the unit square
|
// scale the image to the unit square
|
||||||
ctx.scale(1 / w, -1 / h);
|
ctx.scale(1 / width, -1 / height);
|
||||||
|
|
||||||
var tmpCanvas = createScratchCanvas(w, h);
|
var currentTransform = ctx.mozCurrentTransformInverse;
|
||||||
|
var widthScale = Math.max(Math.abs(currentTransform[0]), 1);
|
||||||
|
var heightScale = Math.max(Math.abs(currentTransform[3]), 1);
|
||||||
|
var tmpCanvas = createScratchCanvas(width, height);
|
||||||
var tmpCtx = tmpCanvas.getContext('2d');
|
var tmpCtx = tmpCanvas.getContext('2d');
|
||||||
this.putBinaryImageData(tmpCtx, imgData, w, h);
|
|
||||||
|
|
||||||
ctx.drawImage(tmpCanvas, 0, -h);
|
if (widthScale >= 2 || heightScale >= 2) {
|
||||||
|
// canvas does not resize well large images to small -- using simple
|
||||||
|
// algorithm to perform pre-scaling
|
||||||
|
tmpCanvas = rescaleImage(imgData.data,
|
||||||
|
width, height,
|
||||||
|
widthScale, heightScale);
|
||||||
|
ctx.scale(widthScale, heightScale);
|
||||||
|
ctx.drawImage(tmpCanvas, 0, -height / heightScale);
|
||||||
|
} else {
|
||||||
|
if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
|
||||||
|
tmpCtx.putImageData(imgData, 0, 0);
|
||||||
|
} else {
|
||||||
|
this.putBinaryImageData(tmpCtx, imgData);
|
||||||
|
}
|
||||||
|
ctx.drawImage(tmpCanvas, 0, -height);
|
||||||
|
}
|
||||||
this.restore();
|
this.restore();
|
||||||
},
|
},
|
||||||
|
|
||||||
putBinaryImageData: function CanvasGraphics_putBinaryImageData(ctx, imgData,
|
putBinaryImageData: function CanvasGraphics_putBinaryImageData(ctx,
|
||||||
w, h) {
|
imgData) {
|
||||||
|
var w = imgData.width, h = imgData.height;
|
||||||
var tmpImgData = 'createImageData' in ctx ? ctx.createImageData(w, h) :
|
var tmpImgData = 'createImageData' in ctx ? ctx.createImageData(w, h) :
|
||||||
ctx.getImageData(0, 0, w, h);
|
ctx.getImageData(0, 0, w, h);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user