本文翻译自:Resizing an image in an HTML5 canvas

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. 我正在尝试使用javascript和canvas元素在客户端创建缩略图,但是当我缩小图像时,它看起来很糟糕。 It looks as if it was downsized in photoshop with the resampling set to 'Nearest Neighbor' instead of Bicubic. 看起来好像是在Photoshop中缩小了尺寸,将重采样设置为“最近的邻居”而不是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. 我尝试使用与[[Source]]链接中所示相同的代码,但是它看起来仍然很糟糕。 Is there something I'm missing, some setting that needs to be set or something? 是否有我所缺少的东西,需要设置的设置或其他东西?

EDIT: 编辑:

I'm trying to resize a jpg. 我正在尝试调整jpg的大小。 I have tried resizing the same jpg on the linked site and in photoshop, and it looks fine when downsized. 我尝试在链接的网站和photoshop中调整相同jpg的大小,缩小尺寸后看起来不错。

Here is the relevant code: 以下是相关代码:

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: 编辑2:

Seems I was mistaken, the linked website wasn't doing any better of a job of downsizing the image. 似乎我弄错了,链接的网站在缩小图像尺寸方面做得更好。 I tried the other methods suggested and none of them look any better. 我尝试了建议的其他方法,但没有一个看起来更好。 This is what the different methods resulted in: 这是不同方法导致的结果:

Photoshop: Photoshop:

Canvas: 帆布:

Image with image-rendering: optimizeQuality set and scaled with width/height: 具有图像渲染的图像:optimizeQuality设置并随宽度/高度缩放:

Image with image-rendering: optimizeQuality set and scaled with -moz-transform: 具有图像渲染的图像:optimizeQuality设置并使用-moz-transform缩放:

Canvas resize on pixastic: 画布在像素上调整大小:

I guess this means firefox isn't using bicubic sampling like its supposed to. 我猜这意味着Firefox并未像预期的那样使用三次三次采样。 I'll just have to wait until they actually add it. 我只需要等待,直到他们实际添加它。

EDIT3: 编辑3:

Original Image 原始图片


#1楼

参考:https://stackoom.com/question/9fII/调整HTML-画布中图像的大小


#2楼

This is a javascript function adapted from @Telanor's code. 这是从@Telanor的代码改编而成的javascript函数。 When passing a image base64 as first argument to the function, it returns the base64 of the resized image. 将图像base64作为第一个参数传递给函数时,它将返回调整后大小的图像的base64。 maxWidth and maxHeight are optional. maxWidth和maxHeight是可选的。

function thumbnail(base64, maxWidth, maxHeight) {// Max size for thumbnailif(typeof(maxWidth) === 'undefined') var maxWidth = 500;if(typeof(maxHeight) === 'undefined') var maxHeight = 500;// Create and initialize two canvasvar canvas = document.createElement("canvas");var ctx = canvas.getContext("2d");var canvasCopy = document.createElement("canvas");var copyContext = canvasCopy.getContext("2d");// Create original imagevar img = new Image();img.src = base64;// Determine new ratio based on max sizevar ratio = 1;if(img.width > maxWidth)ratio = maxWidth / img.width;else if(img.height > maxHeight)ratio = maxHeight / img.height;// Draw original image in second canvascanvasCopy.width = img.width;canvasCopy.height = img.height;copyContext.drawImage(img, 0, 0);// Copy and resize second canvas to first canvascanvas.width = img.width * ratio;canvas.height = img.height * ratio;ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);return canvas.toDataURL();}

#3楼

Thanks @syockit for an awesome answer. 感谢@syockit提供了一个很棒的答案。 however, I had to reformat a little as follows to make it work. 但是,我必须重新格式化以下内容才能使其正常运行。 Perhaps due to DOM scanning issues: 可能是由于DOM扫描问题:

$(document).ready(function () {$('img').on("load", clickA);
function clickA() {var img = this;var canvas = document.createElement("canvas");new thumbnailer(canvas, img, 50, 3);document.body.appendChild(canvas);
}function thumbnailer(elem, img, sx, lobes) {this.canvas = elem;elem.width = img.width;elem.height = img.height;elem.style.display = "none";this.ctx = elem.getContext("2d");this.ctx.drawImage(img, 0, 0);this.img = img;this.src = this.ctx.getImageData(0, 0, img.width, img.height);this.dest = {width: sx,height: Math.round(img.height * sx / img.width)};this.dest.data = new Array(this.dest.width * this.dest.height * 3);this.lanczos = lanczosCreate(lobes);this.ratio = img.width / sx;this.rcp_ratio = 2 / this.ratio;this.range2 = Math.ceil(this.ratio * lobes / 2);this.cacheLanc = {};this.center = {};this.icenter = {};setTimeout(process1, 0, this, 0);
}//returns a function that calculates lanczos weight
function lanczosCreate(lobes) {return function (x) {if (x > lobes)return 0;x *= Math.PI;if (Math.abs(x) < 1e-16)return 1var xx = x / lobes;return Math.sin(x) * Math.sin(xx) / x / xx;}
}process1 = function (self, u) {self.center.x = (u + 0.5) * self.ratio;self.icenter.x = Math.floor(self.center.x);for (var v = 0; v < self.dest.height; v++) {self.center.y = (v + 0.5) * self.ratio;self.icenter.y = Math.floor(self.center.y);var a, r, g, b;a = r = g = b = 0;for (var i = self.icenter.x - self.range2; i <= self.icenter.x + self.range2; i++) {if (i < 0 || i >= self.src.width)continue;var f_x = Math.floor(1000 * Math.abs(i - self.center.x));if (!self.cacheLanc[f_x])self.cacheLanc[f_x] = {};for (var j = self.icenter.y - self.range2; j <= self.icenter.y + self.range2; j++) {if (j < 0 || j >= self.src.height)continue;var f_y = Math.floor(1000 * Math.abs(j - self.center.y));if (self.cacheLanc[f_x][f_y] == undefined)self.cacheLanc[f_x][f_y] = self.lanczos(Math.sqrt(Math.pow(f_x * self.rcp_ratio, 2) + Math.pow(f_y * self.rcp_ratio, 2)) / 1000);weight = self.cacheLanc[f_x][f_y];if (weight > 0) {var idx = (j * self.src.width + i) * 4;a += weight;r += weight * self.src.data[idx];g += weight * self.src.data[idx + 1];b += weight * self.src.data[idx + 2];}}}var idx = (v * self.dest.width + u) * 3;self.dest.data[idx] = r / a;self.dest.data[idx + 1] = g / a;self.dest.data[idx + 2] = b / a;}if (++u < self.dest.width)setTimeout(process1, 0, self, u);elsesetTimeout(process2, 0, self);
};process2 = function (self) {self.canvas.width = self.dest.width;self.canvas.height = self.dest.height;self.ctx.drawImage(self.img, 0, 0);self.src = self.ctx.getImageData(0, 0, self.dest.width, self.dest.height);var idx, idx2;for (var i = 0; i < self.dest.width; i++) {for (var j = 0; j < self.dest.height; j++) {idx = (j * self.dest.width + i) * 3;idx2 = (j * self.dest.width + i) * 4;self.src.data[idx2] = self.dest.data[idx];self.src.data[idx2 + 1] = self.dest.data[idx + 1];self.src.data[idx2 + 2] = self.dest.data[idx + 2];}}self.ctx.putImageData(self.src, 0, 0);self.canvas.style.display = "block";
}
});

#4楼

Fast image resize/resample algorithm using Hermite filter with JavaScript. 使用带有JavaScript的Hermite过滤器的快速图像调整大小/重采样算法。 Support transparency, gives good quality. 支持透明,提供良好的质量。 Preview: 预习:

Update : version 2.0 added on GitHub (faster, web workers + transferable objects). 更新 :在GitHub上添加了2.0版(更快,网络工作者+可转移对象)。 Finally i got it working! 终于我得到了它的工作!

Git: https://github.com/viliusle/Hermite-resize Git: https : //github.com/viliusle/Hermite-resize
Demo: http://viliusle.github.io/miniPaint/ 演示: http : //viliusle.github.io/miniPaint/

/*** Hermite resize - fast image resize/resample using Hermite filter. 1 cpu version!* * @param {HtmlElement} canvas* @param {int} width* @param {int} height* @param {boolean} resize_canvas if true, canvas will be resized. Optional.*/
function resample_single(canvas, width, height, resize_canvas) {var width_source = canvas.width;var height_source = canvas.height;width = Math.round(width);height = Math.round(height);var ratio_w = width_source / width;var ratio_h = height_source / height;var ratio_w_half = Math.ceil(ratio_w / 2);var ratio_h_half = Math.ceil(ratio_h / 2);var ctx = canvas.getContext("2d");var img = ctx.getImageData(0, 0, width_source, height_source);var img2 = ctx.createImageData(width, height);var data = img.data;var data2 = img2.data;for (var j = 0; j < height; j++) {for (var i = 0; i < width; i++) {var x2 = (i + j * width) * 4;var weight = 0;var weights = 0;var weights_alpha = 0;var gx_r = 0;var gx_g = 0;var gx_b = 0;var gx_a = 0;var center_y = (j + 0.5) * ratio_h;var yy_start = Math.floor(j * ratio_h);var yy_stop = Math.ceil((j + 1) * ratio_h);for (var yy = yy_start; yy < yy_stop; yy++) {var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half;var center_x = (i + 0.5) * ratio_w;var w0 = dy * dy; //pre-calc part of wvar xx_start = Math.floor(i * ratio_w);var xx_stop = Math.ceil((i + 1) * ratio_w);for (var xx = xx_start; xx < xx_stop; xx++) {var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half;var w = Math.sqrt(w0 + dx * dx);if (w >= 1) {//pixel too farcontinue;}//hermite filterweight = 2 * w * w * w - 3 * w * w + 1;var pos_x = 4 * (xx + yy * width_source);//alphagx_a += weight * data[pos_x + 3];weights_alpha += weight;//colorsif (data[pos_x + 3] < 255)weight = weight * data[pos_x + 3] / 250;gx_r += weight * data[pos_x];gx_g += weight * data[pos_x + 1];gx_b += weight * data[pos_x + 2];weights += weight;}}data2[x2] = gx_r / weights;data2[x2 + 1] = gx_g / weights;data2[x2 + 2] = gx_b / weights;data2[x2 + 3] = gx_a / weights_alpha;}}//clear and resize canvasif (resize_canvas === true) {canvas.width = width;canvas.height = height;} else {ctx.clearRect(0, 0, width_source, height_source);}//drawctx.putImageData(img2, 0, 0);
}

#5楼

If you're simply trying to resize an image, I'd recommend setting width and height of the image with CSS. 如果您只是想调整图像的大小,建议您使用CSS设置图像的widthheight Here's a quick example: 这是一个简单的示例:

.small-image {width: 100px;height: 100px;
}

Note that the height and width can also be set using JavaScript. 注意, heightwidth也可以使用JavaScript进行设置。 Here's quick code sample: 这是快速的代码示例:

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

Also, to ensure that the resized image looks good, add the following css rules to image selector: 另外,为确保调整后的图像看起来不错,请在图像选择器中添加以下css规则:

  • -ms-interpolation-mode: bicubic : introduce in IE7 -ms-interpolation-mode: bicubic :在IE7中引入
  • image-rendering: optimizeQuality : introduced in FireFox 3.6 image-rendering: optimizeQuality :FireFox 3.6中引入

As far as I can tell, all browsers except IE using an bicubic algorithm to resize images by default, so your resized images should look good in Firefox and Chrome. 据我所知,默认情况下,除IE以外的所有浏览器均使用双三次算法来调整图像大小,因此,在Firefox和Chrome浏览器中,调整大小后的图像应该看起来不错。

If setting the css width and height doesn't work, you may want to play with a css transform : 如果设置CSS的widthheight不起作用,则可能需要使用CSS transform

  • -moz-transform: scale(sx[, sy])
  • -webkit-transform:scale(sx[, sy])

If for whatever reason you need to use a canvas, please note that there are two ways an image can be resize: by resizing the canvas with css or by drawing the image at a smaller size. 如果出于任何原因需要使用画布,请注意可以通过两种方式调整图像的大小:使用CSS调整画布的大小或以较小的尺寸绘制图像。

See this question for more details. 有关更多详细信息,请参见此问题 。


#6楼

i got this image by right clicking the canvas element in firefox and saving as. 我通过右键单击firefox中的canvas元素并将其另存为得到此图像。

var img = new Image();
img.onload = function () {console.debug(this.width,this.height);var canvas = document.createElement('canvas'), ctx;canvas.width = 188;canvas.height = 150;document.body.appendChild(canvas);ctx = canvas.getContext('2d');ctx.drawImage(img,0,0,188,150);
};
img.src = 'original.jpg';

so anyway, here is a 'fixed' version of your example: 因此,无论如何,这是示例的“固定”版本:

var img = new Image();
// added cause it wasnt defined
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);var ctx = canvas.getContext("2d");
var canvasCopy = document.createElement("canvas");
// adding it to the bodydocument.body.appendChild(canvasCopy);var copyContext = canvasCopy.getContext("2d");img.onload = function()
{var ratio = 1;// defining cause it wasntvar maxWidth = 188,maxHeight = 150;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;// the line to change// ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);// the method signature you are using is for slicingctx.drawImage(canvasCopy, 0, 0, canvas.width, canvas.height);
};// changed for example
img.src = 'original.jpg';

调整HTML5画布中图像的大小相关推荐

  1. html5图像调整大小,JavaScript调整HTML5画布中图像的大小

    因此,如果所有浏览器(实际上,Chrome 5给我提供了一个不错的浏览器)都无法为你提供足够好的重采样质量,你该怎么办?然后,你自己实现它们!哦,来吧,我们正在进入Web 3.0的新时代,符合HTML ...

  2. 怎样在html中实现图层重叠,javascript – 在HTML5画布中实现图层

    我即将在HTML5画布中实现Photoshop般的图层.目前我有两个想法.第一个也许更简单的想法是为每个图层设置一个Canvas元素,如: 这样当你画到一个图层 – 它实际上是去"层&quo ...

  3. html5圆圈,javascript – 如何在HTML5画布中绘制带有文本的圆圈

    看起来很简单,可以在 HTML5画布中绘制圆圈和文本,但是我得到了非直观的行为.圆形画得漂亮漂亮,然后画出的圆圈越多,旧圆圈的形状越来越八角形.对我来说很奇怪-此外,文字从旧圆圈中消失,只出现在最后绘 ...

  4. html中画布中怎么画一条直线,使用EaselJS在html5画布中绘制线条

    我对画架和HTML5本身非常新颖.我正试图在使用EaselJS的画布上绘制一条线. X坐标纵坐标固定为100,Y坐标纵坐标从数组列表中获得.我写的代码如下.可以请别人让我知道我哪里出错了?使用Ease ...

  5. 如何在html网页中加入椭圆按钮,如何在HTML5画布中绘制椭圆形?

    您可以尝试运行以下代码在HTML5画布中绘制椭圆形- 示例HTML> //画布 var c = document.getElementById('newCanvas'); var context ...

  6. HTML5画布(图像)

    案例1: <!DOCTYPE html> <html> <head lang="en"><meta charset="UTF-8 ...

  7. html5中画线效果标记是,HTML5画布中怎样绘制线?

    线是所有复杂图形的组成基础,想要绘制复杂的的图形,首先要从绘制线开始.在绘制线之前首先要了解线的组成.一条最简单的线由三部分组成,分别为初始位置.连线端点以及描边,如图1所示. 图1 线的组成 对图1 ...

  8. html画布里增添颜色,在HTML5画布中更改笔触颜色

    我是HTML5画布的新手,我正在玩this example 然后我想在单击颜色选择器时更改笔划的颜色 $("button").click(function() { console. ...

  9. 前端:JS/38/canvas状态的保存和恢复(canvas常用状态大全),canvas画布中图像的变形

    canvas状态的保存和恢复 Saving and restoring state 在了解变形之前,我先介绍两个在你开始绘制复杂图形时必不可少的方法. canvas.save() 保存画布(canva ...

  10. html画布有的电脑显示不出来桌面,不在html5画布中显示图像(javascript)

    我正试图在棋盘上展示棋子.问题是:如果我让"警报(img.src)"(从而创建了很多警报框--),件会在正确的位置显示,但如果我删除警报,它只显示一件在我画布的右上角. 你觉得怎么 ...

最新文章

  1. jquery mobie导致超链接不可用
  2. 演讲实录丨中科大陈小平教授《从封闭性到非封闭性:2020到2035年智能机器的机遇和挑战》...
  3. [Android ] linux命令英文缩写的含义(方便记忆)
  4. Merge和Rebase在Git中的区别
  5. java 内部类 线程_java多线程基本概述(十四)——Thread内部类的几种写法
  6. rest接口自动化测试_REST服务的自动化测试
  7. react发送和接收请求_React行为编程简介:请求,等待和阻止
  8. hdu 1106 字符串处理
  9. Ioc模式(又称DI:Dependency Injection 依赖注射)
  10. 使用过滤器实现网站访问计数器的功能
  11. linux命令关闭浏览器,linux命令行浏览器的使用方法
  12. 2016第二届美亚杯电子数据取证(个人赛)
  13. 谷歌发布智能绘画工具AutoDraw,只要有这个,谁都可以画画。
  14. 13、Activiti7工作流从入门到放弃
  15. 《Python 3网络爬虫开发实战 》崔庆才著 第一章笔记
  16. 数据库实验报告 创建学生关系数据表、课程表、选课表 SQL Kingbase
  17. eNSP之IPsec 虚拟专用网配置
  18. java.util.Date的getYear() .
  19. Autodesk AutoCAD Mac版卸载教程
  20. pcie inbound和outbound关系

热门文章

  1. 「转」AR技术应用 の 照片透视效果
  2. python表单验证wtf_正在验证wtfforms中的美国电话号码
  3. 可见光波长和颜色的对应关系
  4. 2016.3.24 OneZero站立会议
  5. go module 详解
  6. Vue template挂载中el和mouted的使用和区别
  7. vue官网oracle,Oracle企业可视化解决方案AutoVue系列产品更新至v21.0.1
  8. 光伏龙头们掀起垂直一体化狂潮
  9. 2020产品经理升职攻略-直播分享课
  10. Tomcat,Servlet,JSP之间是什么关系?