html图像应用在画布上,HTML 5画布图像:如何应用抗混叠

致因

有些图像很难下移-样本和内插比如这条曲线,当你想从大到小的时候。

浏览器似乎通常使用带画布元素的双线性(2x2采样)插值,而不是双三次(4x4采样),这是出于(可能的)性能原因。

如果步长太大,那么就没有足够的像素来进行采样,而这些像素将反映在结果中。

从信号/dsp的角度来看,您可以看到这是一个低通滤波器的阈值设置太高,这可能导致混叠,如果有许多高频(细节)在信号。

这里有一个很好的技巧,您可以在浏览器中使用它来支持filter属性在2D上下文中。这就模糊了图像,这在本质上和重采样一样,然后缩小。这允许较大的步骤,但只需要两个步骤和两个绘制。

使用步骤的数目(初始大小/目标大小/2)作为半径(您可能需要根据浏览器和奇偶步骤调整这个启发式的步骤-这里只显示了简化的步骤):

const canvas = document.getElementById("canvas");

const ctx = canvas.getContext("2d");

if (typeof ctx.filter === "undefined") {

alert("Sorry, the browser doesn't support Context2D filters.")

}

const img = new Image;

img.onload = function() {

// step 1

const oc = document.createElement('canvas');

const octx = oc.getContext('2d');

oc.width = this.width;

oc.height = this.height;

// steo 2: pre-filter image using steps as radius

const steps = (oc.width / canvas.width)>>1;

octx.filter = `blur(${steps}px)`;

octx.drawImage(this, 0, 0);

// step 3, draw scaled

ctx.drawImage(oc, 0, 0, oc.width, oc.height, 0, 0, canvas.width, canvas.height);

}

img.src = "//i.stack.imgur.com/cYfuM.jpg";

body{ background-color: ivory; }

canvas{border:1px solid red;}

Original was 1600x1200, reduced to 400x300 canvas

对OGF OCT/2018过滤器的支持:

CanvasRenderingContext2D.filter

api.CanvasRenderingContext2D.filter

On Standard Track, Experimental

https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/filter

DESKTOP >        |Chrome    |Edge      |Firefox   |IE        |Opera     |Safari

:----------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------

filter !         |    52    |    ?     |    49    |    -     |    -     |    -

MOBILE >         |Chrome/A  |Edge/mob  |Firefox/A |Opera/A   |Safari/iOS|Webview/A

:----------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------

filter !         |    52    |    ?     |    49    |    -     |    -     |    52

! = Experimental

Data from MDN - "npm i -g mdncomp" (c) epistemex

现在有一个新属性在规范中定义,用于设置重采样质量:context.imageSmoothingQuality = "low|medium|high"

它目前只支持Chrome。每个级别使用的实际方法由供应商来决定,但假设Lanczos的“高”或类似的质量是合理的。这意味着可以跳过所有步骤,或者可以使用更大的步骤来减少重绘,这取决于图像大小和

支持imageSmoothingQuality:

CanvasRenderingContext2D.imageSmoothingQuality

api.CanvasRenderingContext2D.imageSmoothingQuality

On Standard Track, Experimental

https://developer.mozilla.org/docs/Web/API/CanvasRenderingContext2D/imageSmoothingQuality

DESKTOP >              |Chrome    |Edge      |Firefox   |IE        |Opera     |Safari

:----------------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:

imageSmoothingQuality !|    54    |    ?     |    -     |    ?     |    41    |    Y

MOBILE >               |Chrome/A  |Edge/mob  |Firefox/A |Opera/A   |Safari/iOS|Webview/A

:----------------------|:--------:|:--------:|:--------:|:--------:|:--------:|:--------:

imageSmoothingQuality !|    54    |    ?     |    -     |    41    |    Y     |    54

! = Experimental

Data from MDN - "npm i -g mdncomp" (c) epistemex

浏览器。在那之前.:

传输端

解决办法是使用下台才能得到正确的结果。逐步下降意味着您缩小了大小的步骤,以允许有限的插值范围,以涵盖足够的像素采样。

这将允许良好的结果,也与双线性插值(实际上它的行为非常类似于双立方,当这样做)和开销是最小的,因为有更少的像素在每一步采样。

理想的一步就是去决议的一半在每个步骤中,直到设置目标大小为止(感谢JoeMabel提到这一点!)

在这种情况下,您需要分三个步骤下台:

在步骤1中,我们通过使用屏幕外画布将图像减少到一半:// step 1 - create off-screen canvasvar 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);

步骤2重用屏幕外画布并将图像再绘制成一半:// step 2octx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5);

我们再一次画到主画布,再一次缩小到一半但最终的尺寸:// step 3ctx.drawImage(oc, 0, 0, oc.width * 0.5, oc.height * 0.5,

0, 0, canvas.width,   canvas.height);

提示:

您可以使用此公式计算所需步骤的总数(它包括设置目标大小的最后一步):steps = Math.ceil(Math.log(sourceWidth / targetWidth) / Math.log(2))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值