gpt4 book ai didi

javascript - 调整 Canvas 中图像大小时的视觉闪烁

转载 作者:行者123 更新时间:2023-12-03 08:20:26 25 4
gpt4 key购买 nike

我有一个简单的JS动画,它的图像大小更改为小数点后3位,并且在图像的某些部分上引起恼人的闪烁效果。我发现某些图像会产生这种效果,而其他图像则不会。

我想知道动画师如何解决此问题,以消除视觉效果,尤其是在Javascript中。

您将需要查看对JSFiddle的影响。我在此处创建了动画,以查看建筑物上的视觉效果:
http://jsfiddle.net/qerwsn07/

function draw() {
debug.innerHTML = 'Scale: '+scale;
if(!dir){
scale += 0.001;
if(scale > 1.09){
dir = true;
}
} else if(dir) {
scale -= 0.001;
if(scale < 1){
dir = false;
}
}
ctx.clearRect(0, 0, element.width, element.height);
ctx.save()
ctx.translate(element.width/2 - (camera.x / 500),element.height/2 - (camera.y / 500));
var x = - ((img.width * scale) / 2);
var y = - ((img.height* scale) / 2);
var width = img.width * scale;
var height = img.height*scale;

ctx.drawImage(img,x,y,img.width*scale,img.height*scale);
ctx.restore();
requestAnimationFrame(draw);
}
draw();


是否有消除或减少效果的方法?

最佳答案

尽管在我现在使用的计算机上看不到此错误,但我知道您的问题是什么。有两种减少它的方法。

首先,问题是由像素采样引起的。缩放图像时,屏幕像素(设备显示器上的物理像素)与图像中的像素之间不再存在一对一的匹配。缩小(缩小图像)时,图像中的像素多于显示的像素。放大(放大图像)时,像素分布超过一个。

最基本的解决方案称为最近像素采样。硬件计算缩放后的图像上每个设备显示像素的位置,然后选择最接近图像中该点的像素。

最常见的替代方法是双线性插值。在这种方法中,硬件在放大(使图像放大)时使用最接近的4个像素,并通过在左右之间,然后在上下之间进行简单线性插值并显示平均颜色来计算颜色。缩小时,将平均显示像素以下的像素。此方法可大大减少闪烁,但不能完全消除。

画布使您可以在最接近的像素和硬件的平滑模式之间进行选择。用于平滑的内容取决于硬件配置。

要使用平滑方法,请将2D上下文的imageSmoothingEnabled属性设置为true

ctx.imageSmoothingEnabled = true;


要关闭它

ctx.imageSmoothingEnabled = false;


但是默认情况下,对画布而言这是“ true”。因此,我认为这不会立即解决您的问题。

如果您使用的是PC,则您的图形驱动程序可能附带有用于调整渲染性能的实用程序。这些实用程序通常可以在Windows控制面板中找到。根据硬件和使用的驱动程序,选项会有所不同。通常,他们有一个性能面板,您可以在其中设置硬件以提高性能或质量。性能设置将超过画布的平滑选项,并且仅使用最近的像素(或设备最快的像素)。如果已将其设置为最佳质量,请查看是否会改变闪烁。

此外,其中一些实用程序还允许您为每个应用程序设置质量设置。因此,请检查图形设备是否具有该选项以及浏览器是否在列表中。如果是这样,则将其更改为最佳质量。

一些驱动程序允许您设置各个图形选项。因此,请外观并将像素过滤更改为适合您的过滤。您可能必须通过将像素过滤设置为应用程序设置来强制浏览器使用它。
(如果您使用的是Mac,请咨询帮助)

如果一切设置正确,但是仍然闪烁,那么您将不得不使用其他方法来减少问题。

图像模糊;

缩小时使用。 Mip映射的修改。您需要在内存中创建图像的第二个副本,并稍微模糊该图像。缩小时,渲染模糊的图像。您可能还希望在模糊的图像和原始图像之间进行较小的过渡,以防止由于缩放比例从放大切换到缩小而被注意到。这可以通过使用 ctx.globalAlpha将一个图像淡入另一个图像来完成。

Mip映射;

此方法涉及创建图像的许多副本。每个分辨率是前一个分辨率的一半。您将必须使用良好的降采样器(photoshop,Gimp,Paint.net),所有采样器均具有降采样选项。或者,您也可以自己编写一个代码。

当显示缩小的图像时,您将绘制与缩放尺寸最接近的两个图像,并且两者之间的淡入度取决于缩放与下采样图像侧的接近程度。

无论您做什么,缩放时始终仍然会有些伪像。每种方法都有其优点和缺点。为了获得最佳质量,请从分辨率为最大缩放像素的两倍的图像开始。然后,在渲染时,您可以使用首选的采样方法在代码中对图像进行采样(JavaScript不能在2D上下文中完成该工作,您需要使用GPU和webGL)

编辑添加了浏览器平滑测试

我添加了一个小测试,以查看计算机上的图形设备驱动程序是否覆盖了平滑处理。左侧测试图案已平滑,另一方已平滑。如果两者看起来相同,则说明浏览器无法控制平滑。



// this code is not intended as an answer but as a way of checking 
// device smoothing is avalible or not.
var canvas = document.getElementById("canV");
var ctx = canvas.getContext("2d");

// not commented as not a code answer.
var currentSurface = ctx;
var createImage = function (w, h) {
var image = document.createElement("canvas");
image.width = w;
image.height = h !== undefined?h:w;
currentSurface = image.ctx = image.getContext("2d");
return image;
}


var img = createImage(256,256);
var imageDat = img.ctx.getImageData(0,0,255,255);
var dat = imageDat.data;
var ind = 0;
var lines = 2;
var grow = 2;
var black = 0
var white = 255
for(var y = 0; y < 256; y++){
for(var x = 0; x < 256; x++){
if(x%lines < lines-1){
dat[ind++] = black;
dat[ind++] = black;
dat[ind++] = black;
}else{
dat[ind++] = white;
dat[ind++] = white;
dat[ind++] = white;
}
dat[ind++] = 255;
}
if(y%lines < lines-1){
black = 0;
white = 255;
}else{
black = 255;
white = 0;
}
grow += 0.04;
lines = Math.floor(grow);
}
img.ctx.putImageData(imageDat,0,0);
var count = 1000;
var tick = 0;
function update(){
tick += 0.01;
zoom = Math.sin(tick)*64;
ctx.imageSmoothingEnabled = false;
ctx.drawImage(img,64-zoom,64-zoom,zoom*2+128,zoom*2+128,0,0,200,200)
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img,64-zoom,64-zoom,zoom*2+128,zoom*2+128,205,0,200,200)

requestAnimationFrame(update)
}
update();

#canV {
width:405px;
height:200px;
}
.smallText {
font-size:small;
}
b {
color:blue;
}

<div class="smallText">Image on the left is <b>ctx.imageSmoothingEnabled = false;</b> and image on the right is <b>ctx.imageSmoothingEnabled = true;</b>. If they both look the same then the divice driver is overwriting the browser smoothing.</div>
<canvas id="canV" width=405 height=200></canvas>

关于javascript - 调整 Canvas 中图像大小时的视觉闪烁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33768270/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com