You might be working on a project which has an image upload feature that takes images from the user and uploads it to your storage server. Once you have implemented it then you start thinking of optimizing it, so different factors like the format, quality, resolution, size of the image etc… come into consideration.
Later you decide to compress the images to save your storage space, so you implement an image compression feature in the back-end. Now you have saved your storage space. Don’t stop there because you can optimize more, save more resources like bandwidth and CPU cycles. If you have a server with limited resources and has many tasks to run then you are just adding more CPU load.
What if you can save your storage space, bandwidth and reduce server load at the same time. Yes, it is possible, the answer is “Compression at the client side using JavaScript”. Now let’s implement it.
Take advantage of the HTML5 Canvas that is used to draw graphics on a web page. Canvas is just a container for your graphics, JavaScript is used to draw.
Steps
Create an instance of JavaScript FileReader API.
const reader = new FileReader();
Read the input image using FileReader.
reader.readAsDataURL(sourceImage);
Create an instance of Image.
const img = new Image();
Set the result of the FileReader as source for the image.
img.src = event.target.result;
Create a HTML5 Canvas element
const elem = document.createElement("canvas");
Set the width and height of the canvas to match the new dimensions of the image.
elem.width = width; elem.height = height;
Create an object that is used to draw graphics on the canvas.
const ctx = elem.getContext("2d")
The getContext() method returns an object with the properties and methods required for drawing graphics on the canvas. The ‘2d‘ parameter limits us for drawing only 2D graphics.
Now draw the image on the canvas by specifying the position, width and height of the image.
ctx.drawImage(img, 0, 0, width, height);
Export the canvas as a blob or DataURL by specifying MIME type, image quality.
const data = ctx.canvas.toDataURL(img, mime, quality);
or
ctx.canvas.toBlob((blob) => { console.log(blob); //output image as a blob const file = new File([blob], fileName, { type: mime, lastModified: Date.now() }); //output image as a file }, mime, quality);
mime is the “mime type” of the image, like ‘image/jpeg’, ‘image/png’ .
Value of quality ranges from 0 to 1. It is the quality of the output image. If you don’t specify the mime and quality in the toBlob() method then default quality will be set and the mime type will be ‘image/png’.
The final code/* */ compress(e) { const width = 500; const height = 300; const fileName = e.target.files[0].name; const reader = new FileReader(); reader.readAsDataURL(e.target.files[0]); reader.onload = event => { const img = new Image(); img.src = event.target.result; img.onload = () => { const elem = document.createElement("canvas"); elem.width = width; elem.height = height; const ctx = elem.getContext("2d"); // img.width and img.height will contain the original dimensions ctx.drawImage(img, 0, 0, width, height); ctx.canvas.toBlob((blob) => { const file = new File([blob], fileName, { type: "image/jpeg", lastModified: Date.now() }); }, "image/jpeg", 1); }, reader.onerror = error => console.log(error); }; }Note:
If you want to maintain the aspect ratio of the output image then you can set either the width or height as constant and calculate the other dimension.
const width = 600; const scaleFactor = width / img.width; elem.width = width; elem.height = img.height * scaleFactor; ctx.drawImage(img, 0, 0, width, img.height * scaleFactor);
Here we kept width as constant and calculated the scaling factor. To find the relative height just multiply the scaling factor to the original height.
For browsers that don’t support “toBlob” methodUse this polyfill “https://developer.mozilla.org...” .
Modify the toBlob parameters as shown otherwise you will get “function expected” error.
//toBlob polyfill if (!HTMLCanvasElement.prototype.toBlob) { Object.defineProperty(HTMLCanvasElement.prototype, "toBlob", { value: function (callback, type, quality) { var dataURL = this.toDataURL(type, quality).split(",")[1]; setTimeout(function() { var binStr = atob( dataURL ), len = binStr.length, arr = new Uint8Array(len); for (var i = 0; i < len; i++ ) { arr[i] = binStr.charCodeAt(i); } callback( new Blob( [arr], {type: type || "image/png"} ) ); }); } }); } // toBlob usage ctx.canvas.toBlob(function (blob) { console.log(blob); //access blob here }, mimeType, quality);
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/102998.html
序 本文主要解析一下nginx ngx_http_gzip_module以及ngx_http_gzip_static_module中的gzip相关配置参数。 gzip 名称 默认配置 作用域 官方说明 中文解读 模块 gzip gzip off; http, server, location, if in location Enables or disables gzipping of ...
摘要: GitHub Repo Widget showImg(https://travis-ci.org/hustcc/GitHub-Repo-Widget.js.svg?branch=master); showImg(https://img.shields.io/npm/v/github-repo-widget.js.svg?style=flat-square); showImg(http...
摘要:从现状谈及性能优化原文出处性能优化指南如今网络发展迅猛,这对我们构建的互联网平台要求也更高。这就说明,我们在开发时,并没有站在用户的角度上换位思考,更别谈性能优化。因此,我们可通过区分关键资源并调整加载的优先级来实现性能优化。 从web现状谈及性能优化 原文出处:《Karolina Szczur: The State of the Web》 性能优化指南The Internet is ...
摘要:从现状谈及性能优化原文出处性能优化指南如今网络发展迅猛,这对我们构建的互联网平台要求也更高。这就说明,我们在开发时,并没有站在用户的角度上换位思考,更别谈性能优化。因此,我们可通过区分关键资源并调整加载的优先级来实现性能优化。 从web现状谈及性能优化 原文出处:《Karolina Szczur: The State of the Web》 性能优化指南The Internet is ...
摘要:从现状谈及性能优化原文出处性能优化指南如今网络发展迅猛,这对我们构建的互联网平台要求也更高。这就说明,我们在开发时,并没有站在用户的角度上换位思考,更别谈性能优化。因此,我们可通过区分关键资源并调整加载的优先级来实现性能优化。 从web现状谈及性能优化 原文出处:《Karolina Szczur: The State of the Web》 性能优化指南The Internet is ...
阅读 3126·2021-09-30 09:47
阅读 1950·2021-09-22 16:04
阅读 2225·2021-09-22 15:44
阅读 2503·2021-08-25 09:38
阅读 503·2019-08-26 13:23
阅读 1180·2019-08-26 12:20
阅读 2779·2019-08-26 11:59
阅读 1030·2019-08-23 18:40