Kum*_*mpu 37 javascript html5 scaling interpolation canvas
首先:我想做什么?
我有一个查看图像的应用程序.它使用canvas元素渲染图像.你可以放大,你可以缩小,你可以拖动它.这部分现在完美运作.
但是,假设我有一个包含大量文本的图像.它的分辨率为1200x1700,我的画布有1200x900.最初,当缩小时,这会导致渲染分辨率为~560x800.
我的实际绘图如下:
drawImage(src, srcOffsetX, srcOffsetY, sourceViewWidth, sourceViewHeight,
destOffsetX, destOffsetY, destWidth, destHeight);
Run Code Online (Sandbox Code Playgroud)
此图像上的小文字看起来非常非常糟糕,特别是与其他图像查看器(例如IrfanView)或甚至html <img>元素相比时.
我发现浏览器插值算法是导致这个问题的原因.比较不同的浏览器显示,Chrome渲染缩放图像效果最佳,但仍然不够好.
好吧,我在Interwebs的每个角落搜索了4-5个小时,没找到我需要的东西.我找到了"imageSmoothingEnabled"选项,"图像渲染"CSS样式,你不能在画布上使用,在浮动位置渲染和插值算法的许多JavaScript实现(这些我的目的很慢).
你可能会问为什么我告诉你这一切:为了节省你给我答案的时间我已经知道了
那么:有没有更好的快速方法来获得更好的插值?我目前的想法是创建一个图像对象,调整大小(因为img在缩放时具有良好的插值!)然后渲染它.不幸的是,应用img.width似乎只会影响显示的宽度......
更新:感谢西蒙,我可以解决我的问题.这是我使用的动态缩放算法.请注意,它保持纵横比,height参数仅用于避免更多的浮点计算.它现在只缩小.
scale(destWidth, destHeight){
var start = new Date().getTime();
var scalingSteps = 0;
var ctx = this._sourceImageCanvasContext;
var curWidth = this._sourceImageWidth;
var curHeight = this._sourceImageHeight;
var lastWidth = this._sourceImageWidth;
var lastHeight = this._sourceImageHeight;
var end = false;
var scale=0.75;
while(end==false){
scalingSteps +=1;
curWidth *= scale;
curHeight *= scale;
if(curWidth < destWidth){
curWidth = destWidth;
curHeight = destHeight;
end=true;
}
ctx.drawImage(this._sourceImageCanvas, 0, 0, Math.round(lastWidth), Math.round(lastHeight), 0, 0, Math.round(curWidth), Math.round(curHeight));
lastWidth = curWidth;
lastHeight = curHeight;
}
var endTime =new Date().getTime();
console.log("execution time: "+ ( endTime - start) + "ms. scale per frame: "+scale+ " scaling step count: "+scalingSteps);
}
Run Code Online (Sandbox Code Playgroud)
Sim*_*ris 49
你需要多次"下台".您需要将其重新缩放到中间大小,而不是从非常大的图像缩放到非常小的图像.
考虑要以1/6比例绘制的图像.你可以这样做:
var w = 1280;
var h = 853;
ctx.drawImage(img, 0, 0, w/6, h/6);
Run Code Online (Sandbox Code Playgroud)
或者你可以将其绘制为1/2刻度的内存画布,然后再绘制1/2刻度,然后再刻度1/2刻度.结果是1/6比例的图像,但我们使用三个步骤:
var can2 = document.createElement('canvas');
can2.width = w/2;
can2.height = w/2;
var ctx2 = can2.getContext('2d');
ctx2.drawImage(img, 0, 0, w/2, h/2);
ctx2.drawImage(can2, 0, 0, w/2, h/2, 0, 0, w/4, h/4);
ctx2.drawImage(can2, 0, 0, w/4, h/4, 0, 0, w/6, h/6);
Run Code Online (Sandbox Code Playgroud)
然后,您可以将其绘制回原始上下文:
ctx.drawImage(can2, 0, 0, w/6, h/6, 0, 200, w/6, h/6);
Run Code Online (Sandbox Code Playgroud)
你可以看到现场的差异,这里:
var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');
var img = new Image();
var w = 1280;
var h = 853;
img.onload = function() {
// step it down only once to 1/6 size:
ctx.drawImage(img, 0, 0, w/6, h/6);
// Step it down several times
var can2 = document.createElement('canvas');
can2.width = w/2;
can2.height = w/2;
var ctx2 = can2.getContext('2d');
// Draw it at 1/2 size 3 times (step down three times)
ctx2.drawImage(img, 0, 0, w/2, h/2);
ctx2.drawImage(can2, 0, 0, w/2, h/2, 0, 0, w/4, h/4);
ctx2.drawImage(can2, 0, 0, w/4, h/4, 0, 0, w/6, h/6);
ctx.drawImage(can2, 0, 0, w/6, h/6, 0, 200, w/6, h/6);
}
img.src = 'http://upload.wikimedia.org/wikipedia/commons/thumb/a/a4/Equus_quagga_%28Namutoni%2C_2012%29.jpg/1280px-Equus_quagga_%28Namutoni%2C_2012%29.jpg'Run Code Online (Sandbox Code Playgroud)
canvas {
border: 1px solid gray;
}Run Code Online (Sandbox Code Playgroud)
<canvas id="canvas1" width="400" height="400"></canvas>Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
45323 次 |
| 最近记录: |