J'ai besoin d'un moyen de redimensionner les images en JavaScript sans utiliser d'élément HTML.
Mon application HTML mobile prend des photos puis les convertit en chaînes base64. Par la suite, je dois les redimensionner avant de les envoyer à l'API afin d'économiser de l'espace de stockage.
Je cherche un moyen différent et plus approprié de les redimensionner que d'utiliser un élément de toile. Y a-t-il un moyen?
Un moyen d'éviter que le code HTML principal soit affecté consiste à créer un canevas hors écran qui reste en dehors de l'arborescence DOM.
Cela fournira un tampon bitmap et un code natif compilé pour coder les données d'image. C'est simple à faire:
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();
}
Si vous voulez produire un format différent de PNG (valeur par défaut), spécifiez simplement le type comme ceci:
return canvas.toDataURL('image/jpeg', quality); // quality = [0.0, 1.0]
Il est à noter que CORS les restrictions s'appliquent à toDataURL()
.
Si votre application fournit uniquement des images codées en base64 (je suppose qu'il s'agit de data-uri contenant des données en base64?), Vous devez d'abord "charger" l'image:
var img = new Image;
img.onload = resizeImage;
img.src = originalDataUriHere;
function resizeImage() {
var newDataUri = imageToDataUri(this, targetWidth, targetHeight);
// continue from here...
}
Si la source est pure chaîne base 64, ajoutez-lui simplement un en-tête pour en faire un data-uri:
function base64ToDataUri(base64) {
return 'data:image/png;base64,' + base64;
}
Il suffit de remplacer la partie image/png
Par le type représenté par la chaîne base64 (c.-à-d. En faire un argument facultatif).
La réponse de Ken est la bonne, mais son code ne fonctionne pas. J'ai fait quelques ajustements et cela fonctionne maintenant parfaitement. Pour redimensionner un URI de données:
// 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 est de loin la meilleure réponse, je voulais juste souligner que vous devriez implémenter cela avec une fonction asynchrone. Une fois que cela, vous pourriez faire quelque chose comme:
var newDataUri = await resizedataURL(datas,600,600);
Cela attendra le résultat de la fonction avant de passer à l'étape suivante. C'est une façon plus propre d'écrire du code. Voici la fonction de Pierrick avec le petit montage:
// 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);
Pour plus de détails, vous pouvez consulter les documents MDN: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Promise
Oui, vous pouvez. Ces solutions sont bonnes pour redimensionner et pas seulement convertir une image en base64.
Jpg-js et Pica n'utiliseront pas du tout d'éléments dom. Ces bibliothèques ne fonctionnent qu'avec des données d'image, sans éléments dom (canvas et image).
A propos de la toile, restriction de taille voir ceci post
Vous pouvez utiliser une manipulation d'image Base64 brute, comme indiqué ici.
Semble difficile (et pour png seulement) et pourquoi beaucoup choisissent d'utiliser canvas
http://blog.calyptus.eu/seb/2009/05/png-parser-in-javascript/