如何在不使用抗锯齿的情况下拉伸图像

发布于 2024-12-22 12:38:49 字数 1842 浏览 2 评论 0原文

所以我最近遇到了这个: http://www.nicalis.com/

我很好奇:是有没有办法用较小的图像来做这种事情?我的意思是,它是像素艺术,而不是使用每个像素大小四倍的图像,我们不能用代码拉伸它们吗?所以我开始努力实现它。

我尝试了 CSS、Javascript,甚至 HTML,但都不起作用。它们都模糊得非常严重(像这样:http://jsfiddle.net/nUVJt/2/),这让我想到了我的问题:你能在浏览器中拉伸图像而不使用任何抗锯齿吗?

我愿意接受任何建议,无论是使用画布、jQuery、CSS3 还是其他。

感谢您的帮助!

编辑:现在有更好的方法来做到这一点!一种稍微不那么黑客的方式!神奇之处在于:

.pixelated {
    image-rendering: -moz-crisp-edges;
    image-rendering: -o-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    image-rendering: pixelated;
}

这将阻止所有现代浏览器中的抗锯齿功能。它甚至可以在 IE7-8 中工作,但不能在 9 中工作,不幸的是,我不知道在 9 中执行此操作的任何方法(除了下面概述的画布黑客)。 这种方式比使用 JS 快得多,这一点都不好笑。以下是有关这些内容的更多信息: https://developer.mozilla.org/ en-US/docs/CSS/Image-rendering

EDIT2: 因为这还不是官方规范,所以不太可靠。自从我写了上面的内容以来,Chrome 和 FF 似乎都已停止支持它(根据 这篇文章(下面提到了),这真的很烦人。我们可能还得再等几年才能真正开始在 CSS 中使用它,这确实很不幸。

最终编辑:现在有一个官方方法可以做到这一点!有一个名为image-rendering的新属性。它位于 CSS3 规范中。目前的支持超级不稳定,但是Chrome 刚刚添加了支持,之前也是如此很长一段时间后,我们就可以只说 image-rendering: Pixelated; 并且它可以在所有地方工作(yaayy 常青浏览器!)

So I ran across this recently: http://www.nicalis.com/

And I was curious: Is there a way to do this sort of thing with smaller images? I mean, it's pixel art, and rather than using an image with each pixel quadrupled in size couldn't we stretch them with the code? So I started trying to make it happen.

I tried CSS, Javascript, and even HTML, none of which worked. They all blur up really badly (like this: http://jsfiddle.net/nUVJt/2/), which brings me to my question: Can you stretch an image in-browser without any antialiasing?

I'm open to any suggestions, whether it's using a canvas, jQuery, CSS3, or whatever.

Thanks for the help!

EDIT: There's a better way to do this now! A slightly less hackish way! Here's the magic:

.pixelated {
    image-rendering: -moz-crisp-edges;
    image-rendering: -o-crisp-edges;
    image-rendering: -webkit-optimize-contrast;
    -ms-interpolation-mode: nearest-neighbor;
    image-rendering: pixelated;
}

And that'll stop the anti-aliasing in all the modern browsers. It'll even work in IE7-8, but not in 9, and I don't know of any way of doing it in 9, unfortunately (aside from the canvas hack outlined below).
It's not even funny how much faster it is doing it this way than with JS. Here's more info on those: https://developer.mozilla.org/en-US/docs/CSS/Image-rendering

EDIT2: Because this isn't an official spec yet, it's not very reliable. Chrome and FF both seem to have stopped supporting it since I wrote the above (according to this article which was mentioned below), which is really annoying. We're probably going to have to wait a few more years before we really can start using this in CSS, which is really unfortunate.

FINAL EDIT: There is an official way to do this now! There's a new property called image-rendering. It's in the CSS3 spec. Support is super spotty right now, but Chrome just added support so before too long we’ll be able to just say image-rendering: pixelated; and it’ll work all the places (yaayy evergreen browsers!)

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

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

发布评论

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

评论(5

少女情怀诗 2024-12-29 12:38:49

Canvas 文档明确没有指定缩放方法 - 在我自己的测试中,它确实在 Firefox 中非常糟糕地消除了图像锯齿。

下面的代码从源图像(必须来自同一源或来自数据 URI)逐像素复制,并按指定因子对其进行缩放。

需要额外的离屏画布 (src_canvas) 来接收原始源图像,然后将其图像数据逐像素复制到屏幕画布中。

var img = new Image();
img.src = ...;
img.onload = function() {

    var scale = 8;

    var src_canvas = document.createElement('canvas');
    src_canvas.width = this.width;
    src_canvas.height = this.height;

    var src_ctx = src_canvas.getContext('2d');
    src_ctx.drawImage(this, 0, 0);
    var src_data = src_ctx.getImageData(0, 0, this.width, this.height).data;

    var dst_canvas = document.getElementById('canvas');
    dst_canvas.width = this.width * scale;
    dst_canvas.height = this.height * scale;
    var dst_ctx = dst_canvas.getContext('2d');

    var offset = 0;
    for (var y = 0; y < this.height; ++y) {
        for (var x = 0; x < this.width; ++x) {
            var r = src_data[offset++];
            var g = src_data[offset++];
            var b = src_data[offset++];
            var a = src_data[offset++] / 100.0;
            dst_ctx.fillStyle = 'rgba(' + [r, g, b, a].join(',') + ')';
            dst_ctx.fillRect(x * scale, y * scale, scale, scale);
        }
    }
};

工作演示位于 http://jsfiddle.net/alnitak/LwJJR/

编辑 更优化的演示位于 http://jsfiddle.net/alnitak/j8YTe/ 也使用原始图像数据数组作为目标画布。

The Canvas documentation explicitly does not specify a scaling method - in my own tests it did indeed anti-alias the image quite badly in Firefox.

The code below copies pixel by pixel from a source image (which must be from the same Origin or from a Data URI) and scales it by the specified factor.

An extra off-screen canvas (src_canvas) is required to receive the original source image, and its image data is then copied pixel by pixel into an on-screen canvas.

var img = new Image();
img.src = ...;
img.onload = function() {

    var scale = 8;

    var src_canvas = document.createElement('canvas');
    src_canvas.width = this.width;
    src_canvas.height = this.height;

    var src_ctx = src_canvas.getContext('2d');
    src_ctx.drawImage(this, 0, 0);
    var src_data = src_ctx.getImageData(0, 0, this.width, this.height).data;

    var dst_canvas = document.getElementById('canvas');
    dst_canvas.width = this.width * scale;
    dst_canvas.height = this.height * scale;
    var dst_ctx = dst_canvas.getContext('2d');

    var offset = 0;
    for (var y = 0; y < this.height; ++y) {
        for (var x = 0; x < this.width; ++x) {
            var r = src_data[offset++];
            var g = src_data[offset++];
            var b = src_data[offset++];
            var a = src_data[offset++] / 100.0;
            dst_ctx.fillStyle = 'rgba(' + [r, g, b, a].join(',') + ')';
            dst_ctx.fillRect(x * scale, y * scale, scale, scale);
        }
    }
};

Working demo at http://jsfiddle.net/alnitak/LwJJR/

EDIT a more optimal demo is available at http://jsfiddle.net/alnitak/j8YTe/ that also uses a raw image data array for the destination canvas.

如果没有你 2024-12-29 12:38:49

我已经让它适用于画布

var canvas = document.getElementById("canvas"),
    context = canvas.getContext('2d');
context.webkitImageSmoothingEnabled = context.imageSmoothingEnabled = context.mozImageSmoothingEnabled = context.oImageSmoothingEnabled = false;

I've gotten this to work for canvas

var canvas = document.getElementById("canvas"),
    context = canvas.getContext('2d');
context.webkitImageSmoothingEnabled = context.imageSmoothingEnabled = context.mozImageSmoothingEnabled = context.oImageSmoothingEnabled = false;
↘紸啶 2024-12-29 12:38:49

我能想到的唯一方法是通过画布。您可以尝试简单地将图像绘制到画布上,然后缩放画布 - 我认为您不会通过这种方式获得抗锯齿效果。如果仍然这样做,您可以尝试在绘图调用中缩放图像,或者如果不起作用,您可以使用 getImageDataputImageData“手动”更新缩放图像

:第一种方法有效:http://jsfiddle.net/nUVJt/3 /

The only way I can think of is via canvas. You can try simply drawing the image to a canvas and then scaling the canvas -- I think that you won't get anti-aliasing this way. If you still do, you can try either scaling the image in the draw call or if that doesn't work, you could use getImageData and putImageData to scale the image "by hand"

update: first method works: http://jsfiddle.net/nUVJt/3/

罪歌 2024-12-29 12:38:49

没有。浏览器无论如何都会这样做,并且您无法控制缩放算法。

但是,我确信您可以制作一个基于画布的解决方案,但它可能涉及从源图像中复制像素并有策略地将它们绘制到画布中。这会很棘手,但有可能(而且很慢)。

Nope. The browser does it however it does it, and you get no control over scaling algorithms.

However, I'm sure there is a canvas based solution you could make, but it would probably involve copying pixels out of a source image and strategically drawing them into the canvas. It would be tricky, but possible (and slow).

一袭水袖舞倾城 2024-12-29 12:38:49

我不确定,但也许你可以使用图像数据。试试这个功能..

function imageToImageData(image) {
     var canvas = document.createElement("canvas");
     canvas.width = image.width;
     canvas.height = image.height;
     var ctx = canvas.getContext("2d");
     ctx.drawImage(image, 0, 0);
     return ctx.getImageData(0, 0, canvas.width, canvas.height);
}

im not sure but maybe you can use imagedata. try this function..

function imageToImageData(image) {
     var canvas = document.createElement("canvas");
     canvas.width = image.width;
     canvas.height = image.height;
     var ctx = canvas.getContext("2d");
     ctx.drawImage(image, 0, 0);
     return ctx.getImageData(0, 0, canvas.width, canvas.height);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文