基于 Chromium 的浏览器上返回的 canvas.getimagedata() 值不一致

Inconsistent canvas.getimagedata() values returned on Chromium based browsers

提问人:sharkman 提问时间:11/2/2023 最后编辑:sharkman 更新时间:11/3/2023 访问量:55

问:

编辑:解决方案是(奇怪地)激活 willReadFrequently: true 在画布上,Chromium 和 getImageData() 将返回一致的值,请参阅下面的答案。

我目前正在运行一个程序,该程序从之前加载图像的画布中选取一个像素,分析像素中的RGB值,然后根据蓝色和红色值运行计算。canvas.getImageData()

我只在 Chrome/Chromium/Edge 浏览器上遇到了一个奇怪的行为:第一次加载图像时,为特定像素返回的值是,如果我在画布中再次加载完全相同的图像并多次选择完全相同的像素,我现在得到。RGB(181,1,1)canvas.drawImage()canvas.getImageData()RGB(181,1,2)

HTML格式:

<canvas id="canvas" width="500" height="500"></canvas>

JS:

var ctx = document.getElementById("canvas").getContext("2d", {alpha: false,});
    
const IMG = new Image();
IMG.src = "myImage.jpg"

ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("first image draw : " + ctx.getImageData(66, 27, 1, 1).data);

ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("Second image draw : " + ctx.getImageData(66, 27, 1, 1).data);

ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("Third image draw : " + ctx.getImageData(66, 27, 1, 1).data);

ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("Fourth image draw : " + ctx.getImageData(66, 27, 1, 1).data);

ctx.drawImage(IMG, 0, 0, 500, 500);
console.log("fifth image draw : " + ctx.getImageData(66, 27, 1, 1).data);

Chrome上的结果:

"first image draw : 181,1,1,255"
"Second image draw : 181,1,1,255"
"Third image draw : 181,1,2,255"
"Fourth image draw : 181,1,2,255"
"fifth image draw : 181,1,2,255"

Firefox上的结果:

"first image draw : 181,1,2,255"
"Second image draw : 181,1,2,255"
"Third image draw : 181,1,2,255"
"Fourth image draw : 181,1,2,255"
"fifth image draw : 181,1,2,255"

这种行为只发生在基于 chromium 的浏览器上,无论如何我都会得到 webkit/firefox。RGB(181,1,2)

我在 codepen 上重新创建了这种行为:在 chrome/firefox 上打开它并查看区别:https://codepen.io/sh4kman/pen/qBgaNbe

屏幕截图比较

我试过了:

  1. 禁用抗锯齿 (context.imageSmoothingEnabled= false)
  2. 在每次 getImageData() 调用之前/之后清除画布 (canvas.clearRect())

我知道不同的浏览器可以对图像有不同的渲染/舍入颜色,但在这里我在同一个浏览器上有不同的值,总是遵循相同的模式

javascript html5-canvas chromium getimagedata

评论

0赞 Luke Vo 11/2/2023
也许与您的问题无关,但您应该在那里添加一个 Promise 以等待,因为对我来说,有时 IMG 尚未加载,我得到的只是一个黑屏。onload
0赞 sharkman 11/3/2023
是的!没有费心将它包含在代码笔中,但我在我的真实代码中使用了加载事件。仍然遇到这个问题 .addEventlistener(“load”) 虽然

答:

1赞 Danny 11/3/2023 #1

我无法给出实际的答案,但是按照控制台
警告中提到的画布
属性进行试验,我在 Chromium 上得到了不同的结果。
willReadFrequently

Canvas2D:使用 getImageData 的多个回读操作速度更快,属性设置为 true。请参见:https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-will-read-frequentlywillReadFrequently

我分叉了 CodePen 链接并尝试将值更改为 (default)
和 . 它们的行为都彼此不同。
undefinedfalsetrue

定义

默认行为enter image description here

与第三个值一致的行为是1 enter image description here

与第三个值一致的行为是2 enter image description here

Codepen 链接:https://codepen.io/Danny2006/pen/vYbXJWR

评论

0赞 sharkman 11/3/2023
我遇到过这个选项,但我从来没有想过要测试它,因为我只是......不经常阅读画布?它肯定会修复它,谢谢!这是一个奇怪的问题,据我了解,此选项决定是将画布图像存储在 GPU 上还是 CPU 上,以防频繁使用 getImageData() 并出于性能原因。看起来他们绝对没有理由不启用它,即使你调用 getDataImage() 一次?
0赞 Danny 11/3/2023
我真的说不出来。但奇怪的是,工作方式与.falseundefined