Image resizing in JavaScript - Using canvas element. The HTML <canvas> element is used to draw graphics, on the fly, via JavaScript. Resizing images in browser using canvas is relatively simple. drawImage function allows us to render and scale images on canvas element.
It will be bigger in base64. Base64 uses 6 bits per byte to encode data, whereas binary uses 8 bits per byte.
A way to avoid the main HTML to be affected is to create an off-screen canvas that is kept out of the DOM-tree.
This will provide a bitmap buffer and native compiled code to encode the image data. It is straight forward to do:
function imageToDataUri(img, width, height) {
// create an off-screen canvas
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
// set its dimension to target size
canvas.width = width;
canvas.height = height;
// draw source image into the off-screen canvas:
ctx.drawImage(img, 0, 0, width, height);
// encode image to data-uri with base64 version of compressed image
return canvas.toDataURL();
}
If you want to produce a different format than PNG (default) just specify the type like this:
return canvas.toDataURL('image/jpeg', quality); // quality = [0.0, 1.0]
Worth to note that CORS restrictions applies to toDataURL()
.
If your app is giving only base64 encoded images (I assume they are data-uri's with base64 data?) then you need to "load" the image first:
var img = new Image;
img.onload = resizeImage;
img.src = originalDataUriHere;
function resizeImage() {
var newDataUri = imageToDataUri(this, targetWidth, targetHeight);
// continue from here...
}
If the source is pure base-64 string simply add a header to it to make it a data-uri:
function base64ToDataUri(base64) {
return 'data:image/png;base64,' + base64;
}
Just replace the image/png
part with the type the base64 string represents (ie. make it an optional argument).
Ken's answer is the right answer, but his code doesn't work. I made some adjustments on it and it now works perfectly. To resize a Data URI :
// Takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.
function resizedataURL(datas, wantedWidth, wantedHeight)
{
// We create an image to receive the Data URI
var img = document.createElement('img');
// When the event "onload" is triggered we can resize the image.
img.onload = function()
{
// We create a canvas and get its context.
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// We set the dimensions at the wanted size.
canvas.width = wantedWidth;
canvas.height = wantedHeight;
// We resize the image with the canvas method drawImage();
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
var dataURI = canvas.toDataURL();
/////////////////////////////////////////
// Use and treat your Data URI here !! //
/////////////////////////////////////////
};
// We put the Data URI in the image's src attribute
img.src = datas;
}
// Use it like that : resizedataURL('yourDataURIHere', 50, 50);
Pierrick Martellière is far the best answer, I just wanted to point that you should implement that with a async function. Once that, you would be able to do something like:
var newDataUri = await resizedataURL(datas,600,600);
This will wait for the result of the function before going to the next step. It's a cleaner way to write code. Here is the function from Pierrick with the little edit:
// Takes a data URI and returns the Data URI corresponding to the resized image at the wanted size.
function resizedataURL(datas, wantedWidth, wantedHeight){
return new Promise(async function(resolve,reject){
// We create an image to receive the Data URI
var img = document.createElement('img');
// When the event "onload" is triggered we can resize the image.
img.onload = function()
{
// We create a canvas and get its context.
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
// We set the dimensions at the wanted size.
canvas.width = wantedWidth;
canvas.height = wantedHeight;
// We resize the image with the canvas method drawImage();
ctx.drawImage(this, 0, 0, wantedWidth, wantedHeight);
var dataURI = canvas.toDataURL();
// This is the return of the Promise
resolve(dataURI);
};
// We put the Data URI in the image's src attribute
img.src = datas;
})
}// Use it like : var newDataURI = await resizedataURL('yourDataURIHere', 50, 50);
For more details you can check MDN Docs : https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise
Yes, you can. These solutions good for resizing not just converting image to base64.
Jpg-js and Pica will not use dom elements at all. These libs are working only with image data, without dom elements (canvas and image).
About the canvas, size restriction see this post
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With