I'm trying to create a thumbnail image on the client side using javascript and a canvas element, but when I shrink the image down, it looks terrible. It looks as if it was downsized in photoshop with the resampling set to 'Nearest Neighbor' instead of Bicubic. I know its possible to get this to look right, because this site can do it just fine using a canvas as well. I've tried using the same code they do as shown in the "[Source]" link, but it still looks terrible. Is there something I'm missing, some setting that needs to be set or something?
编辑:
我正在调整一张jpg图片的大小。我试过在链接的网站和photoshop中调整相同的jpg图片的大小,缩小后看起来很好。
以下是相关代码:
reader.onloadend = function(e)
{
var img = new Image();
var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
var copyContext = canvasCopy.getContext("2d");
img.onload = function()
{
var ratio = 1;
if(img.width > maxWidth)
ratio = maxWidth / img.width;
else if(img.height > maxHeight)
ratio = maxHeight / img.height;
canvasCopy.width = img.width;
canvasCopy.height = img.height;
copyContext.drawImage(img, 0, 0);
canvas.width = img.width * ratio;
canvas.height = img.height * ratio;
ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
};
img.src = reader.result;
}
EDIT2:
看来我错了,链接网站并没有做任何更好的工作缩小图像。我尝试了其他建议的方法,没有一个看起来更好。这就是不同方法的结果:
ps:
帆布:
使用图像渲染:optimizeQuality设置并按宽度/高度缩放:
使用-moz-transform设置和缩放:
Canvas在pixastic上调整大小:
我猜这意味着firefox没有像它应该的那样使用双三次抽样。我只能等他们真的加进去了。
EDIT3:
原始图像
我把@syockit的答案和降阶方法转换成了一个可重用的Angular服务,有兴趣的朋友可以访问:https://gist.github.com/fisch0920/37bac5e741eaec60e983
我包括了这两种解决方案,因为它们都有各自的优点和缺点。lanczos卷积方法的质量更高,但代价是速度较慢,而逐步降尺度方法产生了合理的抗锯齿结果,而且速度明显更快。
使用示例:
angular.module('demo').controller('ExampleCtrl', function (imageService) {
// EXAMPLE USAGE
// NOTE: it's bad practice to access the DOM inside a controller,
// but this is just to show the example usage.
// resize by lanczos-sinc filter
imageService.resize($('#myimg')[0], 256, 256)
.then(function (resizedImage) {
// do something with resized image
})
// resize by stepping down image size in increments of 2x
imageService.resizeStep($('#myimg')[0], 256, 256)
.then(function (resizedImage) {
// do something with resized image
})
})
我知道这是一个老话题,但它可能对像我这样的人有用,几个月后,我们第一次遇到这个问题。
这里有一些代码,可以在每次重新加载图像时调整图像的大小。我知道这根本不是最优的,但我提供它作为概念的证明。
另外,很抱歉使用jQuery来做简单的选择器,但我觉得语法太舒服了。
$(document).on('ready', createImage);
$(window).on('resize', createImage);
var createImage = function(){
var canvas = document.getElementById('myCanvas');
canvas.width = window.innerWidth || $(window).width();
canvas.height = window.innerHeight || $(window).height();
var ctx = canvas.getContext('2d');
img = new Image();
img.addEventListener('load', function () {
ctx.drawImage(this, 0, 0, w, h);
});
img.src = 'http://www.ruinvalor.com/Telanor/images/original.jpg';
};
html, body{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
background: #000;
}
canvas{
position: absolute;
left: 0;
top: 0;
z-index: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<head>
<meta charset="utf-8" />
<title>Canvas Resize</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
我的createImage函数在文档加载时被调用一次,之后每次窗口接收到调整大小事件时都被调用。
我在Mac电脑上的Chrome 6和Firefox 3.6中进行了测试。这种“技术”对处理器的消耗就像夏天的冰淇淋一样,但它确实奏效了。
如果你只是想调整图像的大小,我建议用CSS设置图像的宽度和高度。这里有一个简单的例子:
.small-image {
width: 100px;
height: 100px;
}
注意,高度和宽度也可以使用JavaScript设置。下面是快速代码示例:
var img = document.getElement("my-image");
img.style.width = 100 + "px"; // Make sure you add the "px" to the end,
img.style.height = 100 + "px"; // otherwise you'll confuse IE
此外,为了确保调整大小的图像看起来不错,在图像选择器中添加以下css规则:
-ms-interpolation-mode: bicubic:在IE7中引入
图像渲染:optimizeQuality:在FireFox 3.6中引入
据我所知,除了IE之外,所有浏览器都默认使用双三次算法来调整图像大小,所以你调整后的图像在Firefox和Chrome中应该看起来不错。
如果设置css的宽度和高度不工作,你可能想玩一个css转换:
-moz-transform: scale(sx[, sy])
-webkit-transform:规模(sx (sy))
如果出于任何原因你需要使用画布,请注意有两种方法可以调整图像的大小:通过css调整画布的大小或以较小的尺寸绘制图像。
请参阅这个问题了解更多细节。
我把@syockit的答案和降阶方法转换成了一个可重用的Angular服务,有兴趣的朋友可以访问:https://gist.github.com/fisch0920/37bac5e741eaec60e983
我包括了这两种解决方案,因为它们都有各自的优点和缺点。lanczos卷积方法的质量更高,但代价是速度较慢,而逐步降尺度方法产生了合理的抗锯齿结果,而且速度明显更快。
使用示例:
angular.module('demo').controller('ExampleCtrl', function (imageService) {
// EXAMPLE USAGE
// NOTE: it's bad practice to access the DOM inside a controller,
// but this is just to show the example usage.
// resize by lanczos-sinc filter
imageService.resize($('#myimg')[0], 256, 256)
.then(function (resizedImage) {
// do something with resized image
})
// resize by stepping down image size in increments of 2x
imageService.resizeStep($('#myimg')[0], 256, 256)
.then(function (resizedImage) {
// do something with resized image
})
})