javascript 如何在没有抗锯齿的情况下拉伸图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8597081/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 03:56:46  来源:igfitidea点击:

How to stretch images with no antialiasing

javascriptcssimageimage-manipulation

提问by Timothy Miller

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

所以我最近遇到了这个: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?

我尝试了 CSS、Javascript 甚至 HTML,但都没有奏效。它们都非常模糊(像这样:http: //jsfiddle.net/nUVJt/2/),这让我想到了我的问题:你能在没有任何抗锯齿的情况下在浏览器中拉伸图像吗?

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

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

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

这将停止所有现代浏览器中的抗锯齿。它甚至可以在 IE7-8 中工作,但不能在 9 中工作,不幸的是,我不知道在 9 中有什么方法可以做到(除了下面概述的画布黑客)。以这种方式这样做比使用 JS 快多少甚至都不好笑。以下是有关这些的更多信息: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 articlewhich 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.

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

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 spottyright now, but Chrome just added supportso before too long we'll be able to just say image-rendering: pixelated;and it'll work all the places (yaayy evergreen browsers!)

最终编辑:现在有一种官方方法可以做到这一点!有一个名为 的新属性image-rendering。它在CSS3 规范中。现在支持非常不稳定,但是Chrome 刚刚添加了支持,所以不久之后我们就可以说它image-rendering: pixelated;可以在所有地方运行(yaayy 常青浏览器!)

采纳答案by Alnitak

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.

Canvas 文档明确没有指定缩放方法 - 在我自己的测试中,它确实在 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.

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

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.

需要额外的屏幕外画布 ( 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);
        }
    }
};

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

http://jsfiddle.net/alnitak/LwJJR/ 上的工作演示

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

编辑http://jsfiddle.net/alnitak/j8YTe/上提供了更优化的演示,该演示还使用原始图像数据数组作为目标画布。

回答by Leonard Meagher

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;

回答by Mark Kahn

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 thinkthat 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 thatdoesn't work, you could use getImageDataand putImageDatato scale the image "by hand"

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

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

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

回答by Alex Wayne

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).

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

回答by Salt Hareket

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

我不确定,但也许您可以使用 imagedata。试试这个功能。。

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);
}