调整图像与JavaScript的canvas(顺利)

我试图用canvas调整一些图像的大小,但是我对如何平滑它们毫无头绪。 在Photoshop,浏览器等。有一些algorithm,他们使用(如双三次,双线性),但我不知道这些是否内置到canvas或不。

这是我的小提琴: http : //jsfiddle.net/EWupT/

var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.width=300 canvas.height=234 ctx.drawImage(img, 0, 0, 300, 234); document.body.appendChild(canvas); 

第一个是正常大小的图像标签,第二个是canvas。 注意canvas如何不平滑。 我怎样才能达到“平稳”?

您可以使用向下步进来获得更好的结果。 调整图像大小时,大多数浏览器似乎使用线性插值而不是双立方体 。

更新已经添加了一个质量属性的规格, imageSmoothingQuality目前只在Chrome中可用。)

除非select不平滑或最近的邻居,否则浏览器总是在缩小图像后插入图像,因为这是低通滤波器的function以避免混叠。

双线性使用2×2像素做内插,而双立方使用4×4,所以通过这样做,你可以在使用双线性插值的同时使双线性插值更接近双线性插值。

 var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var img = new Image(); img.onload = function () { // set size proportional to image canvas.height = canvas.width * (img.height / img.width); // step 1 - resize to 50% var oc = document.createElement('canvas'), octx = oc.getContext('2d'); oc.width = img.width * 0.5; oc.height = img.height * 0.5; octx.drawImage(img, 0, 0, oc.width, oc.height); // step 2 octx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5); // step 3, resize to final size ctx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5, 0, 0, canvas.width, canvas.height); } img.src = "//i.imgur.com/SHo6Fub.jpg"; 
 <img src="//i.imgur.com/SHo6Fub.jpg" width="300" height="234"> <canvas id="canvas" width=300></canvas> 

我创build了一个可重复使用的Angular服务,以便为任何感兴趣的人员处理图像/canvas的高质量调整: https : //gist.github.com/fisch0920/37bac5e741eaec60e983

该服务包括两个解决scheme,因为它们都有自己的优点/缺点。 lanczos卷积方法以较慢的代价获得较高质量,而逐步缩小方法产生合理的反锯齿结果,速度更快。

用法示例:

 angular.module('demo').controller('ExampleCtrl', function (imageService) { // EXAMPLE USAGE // NOTE: it's bad practice to access the DOM inside a controller, // but this is just to show the example usage. // resize by lanczos-sinc filter imageService.resize($('#myimg')[0], 256, 256) .then(function (resizedImage) { // do something with resized image }) // resize by stepping down image size in increments of 2x imageService.resizeStep($('#myimg')[0], 256, 256) .then(function (resizedImage) { // do something with resized image }) }) 

我创build了一个库,允许您在保留所有颜色数据的同时降低任何百分比。

danschumann/limby-resize/blob/master/lib/canvas_resize.html

您可以在浏览器中包含该文件。 结果看起来像photoshop或图像magick,保留所有的颜色数据,平均像素,而不是采取附近的人,并放弃其他人。 它不使用公式来猜测平均值,而是采用确切的平均值。

由于Trung Le Nguyen Nhat的小提琴是不正确的(它只是在最后一步使用原始图像)
我写了自己的一般表演比较:

小提琴

基本上是:

 img.onload = function() { var canvas = document.createElement('canvas'), ctx = canvas.getContext("2d"), oc = document.createElement('canvas'), octx = oc.getContext('2d'); canvas.width = width; // destination canvas size canvas.height = canvas.width * img.height / img.width; var cur = { width: Math.floor(img.width * 0.5), height: Math.floor(img.height * 0.5) } oc.width = cur.width; oc.height = cur.height; octx.drawImage(img, 0, 0, cur.width, cur.height); while (cur.width * 0.5 > width) { cur = { width: Math.floor(cur.width * 0.5), height: Math.floor(cur.height * 0.5) }; octx.drawImage(oc, 0, 0, cur.width * 2, cur.height * 2, 0, 0, cur.width, cur.height); } ctx.drawImage(oc, 0, 0, cur.width, cur.height, 0, 0, canvas.width, canvas.height); } 

基于K3N的答案,我一般重写任何人都想要的代码

 var oc = document.createElement('canvas'), octx = oc.getContext('2d'); oc.width = img.width; oc.height = img.height; octx.drawImage(img, 0, 0); while (oc.width * 0.5 > width) { oc.width *= 0.5; oc.height *= 0.5; octx.drawImage(oc, 0, 0, oc.width, oc.height); } oc.width = width; oc.height = oc.width * img.height / img.width; octx.drawImage(img, 0, 0, oc.width, oc.height); 

更新JSFIDDLE DEMO

这是我的在线演示

我写了一个小的js-utility来裁剪和调整前端的图像。 这里是GitHub项目的链接 。 你也可以从最终形象得到blob发送它。

 import imageSqResizer from './image-square-resizer.js' let resizer = new imageSqResizer( 'image-input', 300, (dataUrl) => document.getElementById('image-output').src = dataUrl; ); //Get blob let formData = new FormData(); formData.append('files[0]', resizer.blob); //get dataUrl document.getElementById('image-output').src = resizer.dataUrl;