我正在制作和图像上传页面,客户端图像调整大小(使用HTML5画布)。一切正常,但问题是图像质量不是很好。
Here is a link到(正在进行中)照片库,其中包含我调整大小/上传代码生成的图片。
你能看出我的意思是质量差吗?锯齿状边缘很多,特别是在缩略图上。关于如何解决这个问题的任何想法?
这是我生成缩略图的javascript:
img.onload = function()
{
var canvasWidth = 150;
var canvasHeight = 150;
var Rz = resizeCanvasSmall(img,canvasID,canvasWidth,canvasHeight);
ctx.drawImage(img,Rz[0],Rz[1],Rz[2],Rz[3],Rz[4],Rz[5],Rz[6],Rz[7]);
dataurl = canvas.toDataURL("image/jpeg",0.8); // File type and quality (0.0->1.0)
UploadFile();
}
// Function to resize canvas (for thumbnail images)
// img = image object, canvas = canvas element ID
function resizeCanvasSmall(img,canvas,width,height)
{
var sx; //The x coordinate where to start clipping
var sy; //The y coordinate where to start clipping
var swidth; //The width of the clipped image
var sheight; //The height of the clipped image
var aspectRatio = width / height;
if (img.width > img.height) // If landscape
{
sheight = img.height;
swidth = img.height * aspectRatio;
sy = 0;
sx = (img.width - swidth) / 2;
}
else //If portrait
{
swidth = img.width;
sheight = img.width / aspectRatio;
sx = 0;
sy = (img.height - sheight) / 2;
}
document.getElementById(canvas).width = width;
document.getElementById(canvas).height = height;
return [sx,sy,swidth,sheight,0,0,width,height];
}
答案 0 :(得分:5)
调整大量数据的一般规则是跳过2的幂,这样你就可以减少混叠伪像,然后在剩下的时间里再做一次最后的调整。例如:如果你需要将1000px重新缩放至68px,则将其缩小至500px,然后是250px,然后是125px,然后是68px。直到最后一个,它始终是2的力量。
此外,您应该保留纵横比,否则您将在对角线上获得时髦的锯齿效果。如果你需要来自非方形源图像的方形缩略图,那么在你仍然较大的情况下尽可能靠近你的目标方块放大,然后在中心裁剪它。 (或者更小并填充它)。您必须不惜一切代价保留纵横比。
为了获得比我所描述的更好的结果,您必须实现自己的调整大小算法,这将慢得多(因为它们将使用JS而不是优化的本机代码)。跳入WebGL也可能是一种选择。
答案 1 :(得分:3)
http://output.jsbin.com/palota/1/
我制作了一个画布大小调整插件。其中一个文件可以包含在前端。它逐像素地进行。它不是抓住附近的像素,而是平均颜色,因此从原始图像到新图像的平均像素颜色是相同的。
https://github.com/danschumann/limby-resize
并且要包含的实际文件是
https://github.com/danschumann/limby-resize/blob/master/lib/canvas_resize.js
它有点慢,因为我们必须查看所有像素并重新分配每一点颜色,但对于那些不常用的工作,它可以工作。
算法背后的数学
假设我们将3个像素调整为2像素。
通常,每个像素将有4个数字:红色,绿色,蓝色,alpha。让我们看一下简化版本,其中像素只有1个数字。
让我们说原始图像是:0 | 100 | 255
常规画布drawImage调整大小将导致0 | 100或0 | 255
这有时很好,但它会丢失细节,它可能是一个非常丑陋和锯齿状的图像。如果你考虑一下,原始中所有颜色的总和是355(0 + 100 + 255),平均像素是118.33。调整后的平均像素数为50或127.5,看起来可能还是非常不同!
在limby-resize中实现的图像算法将产生与imagemagick类似的图像,保留所有像素数据,因此平均像素将是相同的。
我们的算法会生成以下图像:33 | 201.3
(0 * .66 + 100 * .33)| (100 * .33 + 255 * .66)
我们的总数是234.3,平均值是117.15,这将等于第一张图像(如果我们在这个例子中没有舍入到2位小数)。
canvas_resize.js
应该能够包含在前端中,以便更好地调整客户端的大小。
var img, canvas, resized;
img = new Image;
img.onload = function(){
canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
resized = document.createElement('canvas');
resized.width = 300;
resized.height = 500;
// see lib/canvas_resize for window.canvasResize = function(){...}
canvasResize(canvas, resized);
// resized will now be a properly resized version of canvas
}
img.src = '/path/to/img.jpg';
答案 2 :(得分:0)
我不确定幕后使用了什么,但我一直认为Processing.js has a pretty decent looking image resize。该文档有一些示例用法。 (更新:查看调整大小的代码,看起来它与您正在执行的操作类似。除了它从一个图像获取数据并将其移动到另一个图像。)
调整大小时需要注意的另一件事是,如果可能,请始终将图像尺寸减半,以便您的像素更好地排列。理想大小的例子是50%,25%等。