用JavaScript画布调整图像大小(平滑)

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (22)

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

这是我的fiddle: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。注意画布如何不平滑。我怎样才能达到'平滑'?

提问于
用户回答回答于

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

除非选择不平滑或最近的邻居,否则浏览器将在缩小尺寸后插入图像,因为此功能作为低通滤波器以避免混叠。

双线性使用2x2像素来进行插值,而双立方使用4x4,所以通过逐步进行,您可以在使用双线性插值的同时使双线性插值更接近双线性插值。

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>

取决于您的调整大小有多大,如果差异较小,您可以跳过第2步。

在演示中,您可以看到新的结果现在与图像元素非常相似。

用户回答回答于

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

该服务包括两种解决方案,因为它们都有各自的优点/缺点。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
    })
})

扫码关注云+社区