在画布(和 img)上使用最近邻和 CSS 缩放

发布于 2024-12-13 20:30:13 字数 2008 浏览 0 评论 0原文

使用 CSS zoom 属性时,如何说服浏览器使用“最近邻居”,而不是“双线性”或任何其他更高级的缩放算法?

我的设置是一个包含画布的 div,该 div 通过 JavaScript 将其缩放设置为

...
和为了获得最近的邻居,我在 CSS 中使用 image-rendering: -webkit-optimize-contrast 。该应用程序可在此处使用(“z”放大,“shift-z”缩小),我的CSS是此处

这是 OSX 上 Chrome 中所需的效果(缩放设置为 3200%): 使用最近邻在 OSX/Chrome 上缩放

但在 Windows 7 上的 Chrome 中也有同样的情况: 在 Windows/Chrome 上缩放,不使用最近邻

在这两种情况下,它都是“vanilla”Chrome(版本 15.xx)框中,没有打开实验标志。

如何说服 Windows 上的 Chrome 使用最近邻居?就此而言,我如何才能说服所有浏览器? Safari 也不使用最近邻(到目前为止,该应用程序仅适用于基于 WebKit 的浏览器)

CSS image-rendering 属性确实会影响 Chrome /OSX 并给了我想要的效果。但 Chrome/Windows 和 Safari(5.1)/OSX 似乎都完全忽略了它。有些感觉告诉我我只是运气不好,但我想我应该问一下。

在 div 容器上使用 zoom 非常简单,并且在 Chrome/OSX 中运行得非常好,如果我必须在内部缩放画布,我也可以这样做。但如果可能的话,我更喜欢一行代码解决方案!

更新:我发现使用image-rendering:optimizeSpeed有帮助。然而,它在 Chrome/Windows 中似乎很挑剔。如果我将其设置在太多元素上(我最初尝试过,我的容器和所有画布),它不会生效。但如果我只将其应用到 canvas 上,我就可以完成 98% 的任务。

现在我的问题是我第一次在放大时绘制,它工作得很好,所有其他后续绘制操作在发生时都是模糊的,然后恢复到正确的最近邻居(我的应用程序首先绘制到草稿画布中,然后将绘图应用到真实的画布上)。 Chrome 坚持使用双线性的草稿画布有些奇怪。我认为通过一些挖掘我可以解决这个问题。

更新2: Chrome/Windows 上的image-rendering 似乎没有很好地实现,并且存在一些问题。我现在可以确认 Chrome/Windows 不支持 optimizeSpeedoptimizeQuality 值。如果您为它们设置图像渲染,Chrome 将忽略该设置。 Chrome/Windows 确实可以识别 -webkit-optimize-contrast,但它并不能一致地使用它。 Chrome 会几乎随机地在双线性缩放算法和最近邻算法之间切换。我无法始终如一地让 Chrome 使用最近邻居。

我尝试在 Windows 上构建 Chromium 17,其行为方式相同。

Firefox (8.0.1) 看起来很有前途,因为它似乎很好地遵守了 -moz-crisp-edges 。最初我将 Chrome 定位为这个应用程序的“理想浏览器”,我可能会切换到 Firefox。

最后,Chrome 似乎正在酝酿对图像渲染的适当支持,只是还没有完全实现。 WebKit 本身声称完全支持所有图像渲染值,但我猜测 Chrome 使用的 WebKit 构建尚未完全更新到此新修复。

When using the CSS zoom property, how can I convince the browser to use "nearest neighbor", instead of "bilinear" or any other more advanced zooming algorithms?

My setup is a div that contains a canvas, and the div gets its zoom set via JavaScript to be <div style="zoom:3200%">...</div> and to get nearest neighbor, I am using image-rendering: -webkit-optimize-contrast in my CSS. The app is available here ('z' zooms in, 'shift-z' zooms back out), and my css is here

Here is the desired effect in Chrome on OSX (zoom is set to 3200%):
zoom on OSX/Chrome using nearest neighbor

But here is the same thing in Chrome on Windows 7:
zoom on Windows/Chrome not using nearest neighbor

In both cases it is "vanilla" Chrome (version 15.x.x) out of the box, no experimental flags are turned on.

How can I convince Chrome on Windows to use nearest neighbor? For that matter, how can I convince all browsers? Safari also does not use nearest neighbor (so far the app only works in WebKit based browsers)

The CSS image-rendering property does affect Chrome/OSX and gives me the desired effect. But Chrome/Windows and Safari(5.1)/OSX both seem to completely ignore it. Something tells me I'm just out of luck, but I figured I'd ask.

Using zoom on the div container is so simple and works beautifully in Chrome/OSX, if I must resort to scaling my canvases internally, I can do that too. But would prefer the literally one line of code solution if possible!

UPDATE: I have found the use of image-rendering: optimizeSpeed helps. However it seems finicky in Chrome/Windows. If I set it on too many elements (I initially tried, my containers and all canvases), it doesn't take effect. But if I apply it to just canvas, I get 98% of the way there.

Now my problem is the first time I draw while zoomed in, it works perfectly, all other subsequent drawing actions are fuzzy while they are taking place, then revert to the correct nearest-neighbor afterwards (my app draws into a scratch canvas first, then applies the drawing to the real canvas). There is something odd about the scratch canvas where Chrome insists on using bilinear. I think with some digging I can resolve that.

UPDATE2: It seems like image-rendering on Chrome/Windows just isn't implemented well and is a bit buggy. I can now confirm that the values optimizeSpeed and optimizeQuality are not supported on Chrome/Windows. If you set image-rendering to them, Chrome will ignore the set. Chrome/Windows does recognize -webkit-optimize-contrast, however it does not use it consistently. Chrome will flip between what looks to be a bilinear scaling algorithm and nearest-neighbor almost at random. I've not been able to consistently get Chrome to use nearest-neighbor.

I tried a build of Chromium 17 on Windows and it behaves the same way.

Firefox (8.0.1) is looking pretty promising though as it does seem to honor -moz-crisp-edges quite well. Originally I was targeting Chrome as my "ideal browser" for this app, I might just switch over to Firefox.

In the end, it seems like proper support for image-rendering is in the pipeline for Chrome, just not quite there yet. WebKit itself claims to fully support all image-rendering values, but I'm guessing the build of WebKit that Chrome uses hasn't quite updated to this new fix.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

下壹個目標 2024-12-20 20:30:13

有一个办法。我在这里问了一个与此类似的问题:如何在没有抗锯齿的情况下拉伸图像 并得到了非常好的回应。从那时起,我对它进行了相当多的修改,但这是一个简单的版本,单击时会拉伸(没有抗锯齿): http://jsfiddle.net/howlermiller/U2eBZ/1/

不过,这是令人难以置信的黑客行为。除非必须,否则不要使用它。每次点击图像时它都必须重新创建图像,因此对于大图像来说,速度会很慢而且很糟糕。但它确实可以在 Chrome/Windows 上运行。

编辑: 支持此功能现已支持 CSS3 规范! 支持超级不稳定< /a> 在目前,但是 Chrome 刚刚添加了支持,所以我希望我们能够使用不久之后。美好时光!

.thing {
  /* IE, only works on <img> tags */
  -ms-interpolation-mode: nearest-neighbor;
  /* Firefox */
  image-rendering: crisp-edges;
  /* Chromium + Safari */
  image-rendering: pixelated;
}

演示

There is a way. I asked a question similar to this over here: How to stretch images with no antialiasing and got a really good response. I've modified it quite a bit since then, but here's a simple version which stretches (w/out anti-aliasing) when clicked: http://jsfiddle.net/howlermiller/U2eBZ/1/

It's incredibly hackish though. Don't use it unless you must. It has to re-create the image every time you click on it, so with a big image it would be slow and terrible. But it does work on Chrome/Windows.

Edit: This is supported in the CSS3 spec now! Support is super spotty at the moment, but Chrome just added support so I'm hopeful that we'll be able to use it before too long. Good times!

.thing {
  /* IE, only works on <img> tags */
  -ms-interpolation-mode: nearest-neighbor;
  /* Firefox */
  image-rendering: crisp-edges;
  /* Chromium + Safari */
  image-rendering: pixelated;
}

Demo

两仪 2024-12-20 20:30:13

ctx.webkitImageSmoothingEnabled=false 现在似乎从 22 开始就可以工作。

ctx.webkitImageSmoothingEnabled=false now seems to work since 22.

这样的小城市 2024-12-20 20:30:13

由于您无论如何都在使用画布,因此您也可以实现自己的缩放并手动实现最近邻居调整大小。

我怀疑即使你解决了这个问题,有一天你也会遇到其他问题。

@Timothy 的答案似乎有一些很好的代码,您可以使用它来帮助进行实际的数学计算。

Since you're using canvas anyway, you might as well implement your own zoom and manually implement nearest neighbour resizing.

I suspect even if you solve this problem, you'll run into something else one day.

@Timothy's answer seems to have some good code you can use to help with the actual math.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文