web-dev-qa-db-fra.com

Obtenir des données d'image en JavaScript?

J'ai une page HTML normale avec quelques images (seulement des balises <img /> HTML normales). J'aimerais obtenir leur contenu, encodé en base64 de préférence, sans avoir à retélécharger l'image (c'est-à-dire qu'elle est déjà chargée par le navigateur, alors maintenant je veux le contenu).

J'aimerais réaliser cela avec Greasemonkey et Firefox.

310
Detariael

Remarque: Ceci ne fonctionne que si l'image provient du même domaine que la page, ou possède l'attribut crossOrigin="anonymous" et que le serveur prend en charge CORS. Cela ne va pas non plus vous donner le fichier original, mais une version ré-encodée. Si vous voulez que le résultat soit identique à l'original, voir Réponse de Kaiido .


Vous devrez créer un élément de canevas avec les dimensions correctes et copier les données d'image avec la fonction drawImage. Vous pouvez ensuite utiliser la fonction toDataURL pour obtenir une donnée: url contenant l’image encodée en base 64. Notez que l'image doit être entièrement chargée ou vous obtiendrez simplement une image vide (noire, transparente).

Ce serait quelque chose comme ça. Je n'ai jamais écrit de script Greasemonkey, vous devrez donc peut-être ajuster le code pour qu'il s'exécute dans cet environnement.

function getBase64Image(img) {
    // Create an empty canvas element
    var canvas = document.createElement("canvas");
    canvas.width = img.width;
    canvas.height = img.height;

    // Copy the image contents to the canvas
    var ctx = canvas.getContext("2d");
    ctx.drawImage(img, 0, 0);

    // Get the data-URL formatted image
    // Firefox supports PNG and JPEG. You could check img.src to
    // guess the original format, but be aware the using "image/jpg"
    // will re-encode the image.
    var dataURL = canvas.toDataURL("image/png");

    return dataURL.replace(/^data:image\/(png|jpg);base64,/, "");
}

Obtenir une image au format JPEG ne fonctionne pas sur les anciennes versions (environ 3.5) de Firefox. Par conséquent, si vous souhaitez prendre en charge cette fonctionnalité, vous devrez vérifier la compatibilité. Si l'encodage n'est pas pris en charge, il utilisera par défaut "image/png".

387
Matthew Crumley

Cette fonction prend l'URL puis renvoie l'image BASE64

function getBase64FromImageUrl(url) {
    var img = new Image();

    img.setAttribute('crossOrigin', 'anonymous');

    img.onload = function () {
        var canvas = document.createElement("canvas");
        canvas.width =this.width;
        canvas.height =this.height;

        var ctx = canvas.getContext("2d");
        ctx.drawImage(this, 0, 0);

        var dataURL = canvas.toDataURL("image/png");

        alert(dataURL.replace(/^data:image\/(png|jpg);base64,/, ""));
    };

    img.src = url;
}

Appelez ça comme ça: getBase64FromImageUrl("images/slbltxt.png")

73
MuniR

Venir longtemps après, mais aucune des réponses ici n’est tout à fait correcte.

Lorsqu'elle est dessinée sur une toile, l'image transmise est décompressée + toutes les données sont déjà multipliées.
Une fois exporté, il est décompressé ou non avec un algorithme différent et non multiplié.

Tous les navigateurs et appareils auront des erreurs d'arrondis différentes lors de ce processus
(voir empreinte de la toile ).

Donc, si on veut une version base64 d'un fichier image, il faut qu'elle demande à nouveau (la plupart du temps, cela vient du cache) mais cette fois-ci en tant que Blob. 

Ensuite, vous pouvez utiliser un FileReader pour le lire en tant que ArrayBuffer ou en tant que dataURL.

function toDataURL(url, callback){
    var xhr = new XMLHttpRequest();
    xhr.open('get', url);
    xhr.responseType = 'blob';
    xhr.onload = function(){
      var fr = new FileReader();
    
      fr.onload = function(){
        callback(this.result);
      };
    
      fr.readAsDataURL(xhr.response); // async call
    };
    
    xhr.send();
}

toDataURL(myImage.src, function(dataURL){
  result.src = dataURL;

  // now just to show that passing to a canvas doesn't hold the same results
  var canvas = document.createElement('canvas');
  canvas.width = myImage.naturalWidth;
  canvas.height = myImage.naturalHeight;
  canvas.getContext('2d').drawImage(myImage, 0,0);

  console.log(canvas.toDataURL() === dataURL); // false - not same data
  });
<img id="myImage" src="https://dl.dropboxusercontent.com/s/4e90e48s5vtmfbd/aaa.png" crossOrigin="anonymous">
<img id="result">

40
Kaiido

En plus de la réponse de matthew, je voudrais dire que image.width et image.height renvoient la taille affichée de l'image (et rognez l'image lorsque vous la dessinez sur la toile).

Utilisez plutôt naturalWidth et naturalHeight, qui utilise l'image en taille réelle.

Voir http://www.whatwg.org/specs/web-apps/current-work/multipage/edits.html#dom-img-naturalwidth

22
cube45

Une version plus moderne de la réponse de kaiido utilisant fetch serait:

function toDataURL(url) {
  return fetch(url)
      .then((response)=> {
        return response.blob();
      })
      .then(blob=> {
        return URL.createObjectURL(blob);
      });
}

https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

11
Zaptree

Utilisez l'événement onload pour convertir l'image après le chargement

function loaded(img) {
  let c = document.createElement('canvas')
  c.getContext('2d').drawImage(img, 0, 0)
  msg.innerText= c.toDataURL();
}
pre { Word-wrap: break-Word; width: 500px; white-space: pre-wrap; }
<img onload="loaded(this)" src="https://cors-anywhere.herokuapp.com/http://lorempixel.com/200/140" crossorigin="anonymous"/>

<pre id="msg"></pre>
1
Kamil Kiełczewski

En HTML5, mieux utiliser ceci:

{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}
0
KepHec