尽管浏览器渲染优化会导致效果不佳,但如何使用 HTML5 画布实现高质量图像缩小?
HTML5 Canvas:以高质量缩小图像
问题:使用 HTML5 canvas 缩小图像会导致低质量尽管启用了图像渲染优化,但仍然输出。
解决方案:
缩小 HTML5 画布中的图像涉及将原始图像中的多个像素转换为缩放图像中的单个像素。浏览器中常见的缩小技术处理此过程效率低下,导致细节和噪声丢失。
要实现高质量的缩小,请考虑使用像素完美算法来准确计算所有源像素对目标的贡献
算法:
<code class="javascript">// scales the canvas by (float) scale < 1 // returns a new canvas containing the scaled image. function downScaleCanvas(cv, scale) { if (!(scale < 1) || !(scale > 0)) throw ('scale must be a positive number <1 '); var sqScale = scale * scale; // square scale = area of source pixel within target var sw = cv.width; // source image width var sh = cv.height; // source image height var tw = Math.floor(sw * scale); // target image width var th = Math.floor(sh * scale); // target image height var sx = 0, sy = 0, sIndex = 0; // source x,y, index within source array var tx = 0, ty = 0, yIndex = 0, tIndex = 0; // target x,y, x,y index within target array var tX = 0, tY = 0; // rounded tx, ty var w = 0, nw = 0, wx = 0, nwx = 0, wy = 0, nwy = 0; // weight / next weight x / y // weight is weight of current source point within target. // next weight is weight of current source point within next target's point. var crossX = false; // does scaled px cross its current px right border ? var crossY = false; // does scaled px cross its current px bottom border ? var sBuffer = cv.getContext('2d'). getImageData(0, 0, sw, sh).data; // source buffer 8 bit rgba var tBuffer = new Float32Array(3 * tw * th); // target buffer Float32 rgb var sR = 0, sG = 0, sB = 0; // source's current point r,g,b for (sy = 0; sy < sh; sy++) { ty = sy * scale; // y src position within target tY = 0 | ty; // rounded : target pixel's y yIndex = 3 * tY * tw; // line index within target array crossY = (tY != (0 | ty + scale)); if (crossY) { // if pixel is crossing botton target pixel wy = (tY + 1 - ty); // weight of point within target pixel nwy = (ty + scale - tY - 1); // ... within y+1 target pixel } for (sx = 0; sx < sw; sx++, sIndex += 4) { tx = sx * scale; // x src position within target tX = 0 | tx; // rounded : target pixel's x tIndex = yIndex + tX * 3; // target pixel index within target array crossX = (tX != (0 | tx + scale)); if (crossX) { // if pixel is crossing target pixel's right wx = (tX + 1 - tx); // weight of point within target pixel nwx = (tx + scale - tX - 1); // ... within x+1 target pixel } sR = sBuffer[sIndex ]; // retrieving r,g,b for curr src px. sG = sBuffer[sIndex + 1]; sB = sBuffer[sIndex + 2]; if (!crossX && !crossY) { // pixel does not cross // just add components weighted by squared scale. tBuffer[tIndex ] += sR * sqScale; tBuffer[tIndex + 1] += sG * sqScale; tBuffer[tIndex + 2] += sB * sqScale; } else if (crossX && !crossY) { // cross on X only w = wx * scale; // add weighted component for current px tBuffer[tIndex ] += sR * w; tBuffer[tIndex + 1] += sG * w; tBuffer[tIndex + 2] += sB * w; // add weighted component for next (tX+1) px nw = nwx * scale tBuffer[tIndex + 3] += sR * nw; tBuffer[tIndex + 4] += sG * nw; tBuffer[tIndex + 5] += sB * nw; } else if (crossY && !crossX) { // cross on Y only w = wy * scale; // add weighted component for current px tBuffer[tIndex ] += sR * w; tBuffer[tIndex + 1] += sG * w; tBuffer[tIndex + 2] += sB * w; // add weighted component for next (tY+1) px nw = nwy * scale tBuffer[tIndex + 3 * tw ] += sR * nw; tBuffer[tIndex + 3 * tw + 1] += sG * nw; tBuffer[tIndex + 3 * tw + 2] += sB * nw; } else { // crosses both x and y : four target points involved // add weighted component for current px w = wx * wy; tBuffer[tIndex ] += sR * w; tBuffer[tIndex + 1] += sG * w; tBuffer[tIndex + 2] += sB * w; // for tX + 1; tY px nw = nwx * wy; tBuffer[tIndex + 3] += sR * nw; tBuffer[tIndex + 4] += sG * nw; tBuffer[tIndex + 5] += sB * nw; // for tX ; tY + 1 px nw = wx * nwy; tBuffer[tIndex + 3 * tw ] += sR * nw; tBuffer[tIndex + 3 * tw + 1] += sG * nw; tBuffer[tIndex + 3 * tw + 2] += sB * nw; // for tX + 1 ; tY +1 px nw = nwx * nwy; tBuffer[tIndex + 3 * tw + 3] += sR * nw; tBuffer[tIndex + 3 * tw + 4] += sG * nw; tBuffer[tIndex + 3 * tw + 5] += sB * nw; } } // end for sx } // end for sy // create result canvas var resCV = document.createElement('canvas'); resCV.width = tw; resCV.height = th; var resCtx = resCV.getContext('2d'); var imgRes = resCtx.getImageData(0, 0, tw, th); var tByteBuffer = imgRes.data; // convert float32 array into a UInt8Clamped Array var pxIndex = 0; // for (sIndex = 0, tIndex = 0; pxIndex < tw * th; sIndex += 3, tIndex += 4, pxIndex++) { tByteBuffer[tIndex] = Math.ceil(tBuffer[sIndex]); tByteBuffer[tIndex + 1] = Math.ceil(tBuffer[sIndex + 1]); tByteBuffer[tIndex + 2] = Math.ceil(tBuffer[sIndex + 2]); tByteBuffer[tIndex + 3] = 255; } // writing result to canvas. resCtx.putImageData(imgRes, 0, 0); return resCV; }</code>
附加说明:
- 上采样也可以通过使用大于 1 的比例来实现相同的算法。
- 该算法占用大量内存,可能不适合非常大的图像或实时应用程序。
- 适用于较小的图像或非关键用途在这种情况下,使用浏览器默认的 2X 比例或应用双线性插值等更简单的方法可能就足够了。
以上是尽管浏览器渲染优化会导致效果不佳,但如何使用 HTML5 画布实现高质量图像缩小?的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

JavaScript在Web开发中的主要用途包括客户端交互、表单验证和异步通信。1)通过DOM操作实现动态内容更新和用户交互;2)在用户提交数据前进行客户端验证,提高用户体验;3)通过AJAX技术实现与服务器的无刷新通信。

JavaScript在现实世界中的应用包括前端和后端开发。1)通过构建TODO列表应用展示前端应用,涉及DOM操作和事件处理。2)通过Node.js和Express构建RESTfulAPI展示后端应用。

理解JavaScript引擎内部工作原理对开发者重要,因为它能帮助编写更高效的代码并理解性能瓶颈和优化策略。1)引擎的工作流程包括解析、编译和执行三个阶段;2)执行过程中,引擎会进行动态优化,如内联缓存和隐藏类;3)最佳实践包括避免全局变量、优化循环、使用const和let,以及避免过度使用闭包。

Python和JavaScript在社区、库和资源方面的对比各有优劣。1)Python社区友好,适合初学者,但前端开发资源不如JavaScript丰富。2)Python在数据科学和机器学习库方面强大,JavaScript则在前端开发库和框架上更胜一筹。3)两者的学习资源都丰富,但Python适合从官方文档开始,JavaScript则以MDNWebDocs为佳。选择应基于项目需求和个人兴趣。

Python和JavaScript在开发环境上的选择都很重要。1)Python的开发环境包括PyCharm、JupyterNotebook和Anaconda,适合数据科学和快速原型开发。2)JavaScript的开发环境包括Node.js、VSCode和Webpack,适用于前端和后端开发。根据项目需求选择合适的工具可以提高开发效率和项目成功率。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。 1)C 用于解析JavaScript源码并生成抽象语法树。 2)C 负责生成和执行字节码。 3)C 实现JIT编译器,在运行时优化和编译热点代码,显着提高JavaScript的执行效率。

JavaScript在网站、移动应用、桌面应用和服务器端编程中均有广泛应用。1)在网站开发中,JavaScript与HTML、CSS一起操作DOM,实现动态效果,并支持如jQuery、React等框架。2)通过ReactNative和Ionic,JavaScript用于开发跨平台移动应用。3)Electron框架使JavaScript能构建桌面应用。4)Node.js让JavaScript在服务器端运行,支持高并发请求。
