Uzyskać adres URL danych obrazu w JavaScript?

Mam zwykłą stronę HTML z kilkoma obrazkami (zwykłe znaczniki HTML <img />). Chciałbym, aby ich zawartość, base64 zakodowane najlepiej, bez konieczności ponownego pobierania obrazu (tj. jest już załadowany przez przeglądarkę, więc teraz chcę zawartość).

Chciałbym to osiągnąć z Greasemonkey i Firefox.

Author: Kamil Kiełczewski, 2009-06-01

8 answers

Uwaga: {[6] } to działa tylko wtedy, gdy obraz pochodzi z tej samej domeny co Strona, lub ma atrybut crossOrigin="anonymous" i serwer obsługuje CORS. To również nie da ci oryginalnego pliku, ale ponownie zakodowaną wersję. Jeśli chcesz, aby wynik był identyczny z oryginałem, zobacz odpowiedź kaIdō .


Będziesz musiał utworzyć element canvas o prawidłowych wymiarach i skopiować dane obrazu za pomocą funkcji drawImage. Następnie możesz użyć funkcji toDataURL, aby uzyskać dane: url z zakodowanym obrazem base-64. Zauważ, że obraz musi być w pełni załadowany, albo po prostu otrzymasz pusty (czarny, przezroczysty) obraz.

To byłoby coś takiego. Nigdy nie napisałem skryptu Greasemonkey, więc być może będziesz musiał dostosować kod, aby działał w tym środowisku.
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,/, "");
}

Uzyskanie obrazu w FORMACIE JPEG nie działa na starszych wersjach (około 3.5) Firefoksa, więc jeśli chcesz go obsługiwać, musisz sprawdzić zgodność. Jeśli kodowanie nie jest obsługiwane, domyślnie będzie to "image / png".

 406
Author: Matthew Crumley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:09

Ta funkcja pobiera adres URL, a następnie zwraca obraz 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;
}

Nazwij to tak : getBase64FromImageUrl("images/slbltxt.png")

 77
Author: MuniR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-10 18:18:36

Nadchodzi długo po, ale żadna z odpowiedzi tutaj nie są całkowicie poprawne.

Po narysowaniu na płótnie, przekazany obraz jest nieskompresowany + wszystkie wstępnie pomnożone.
Po wyeksportowaniu jest nieskompresowany lub skompresowany za pomocą innego algorytmu i nie zwielokrotniony.

Wszystkie przeglądarki i urządzenia będą miały różne błędy zaokrąglania występujące w tym procesie
(zobacz Canvas fingerprinting ).

Więc jeśli ktoś chce wersję Base64 pliku graficznego, musi request it again (większość czasu będzie pochodzić z pamięci podręcznej), ale tym razem jako Blob.

Następnie możesz użyć FileReader , aby odczytać go jako ArrayBuffer lub jako 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">
 66
Author: Kaiido,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-17 18:22:17

Bardziej nowoczesna wersja odpowiedzi kaIdō za pomocą fetch brzmiałaby:

function toObjectUrl(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

Edit: jak zaznaczono w komentarzach, zwróci To Adres URL obiektu, który wskazuje na plik w lokalnym systemie, a nie na rzeczywisty DataURL, więc w zależności od przypadku użycia może to nie być to, czego potrzebujesz.

Możesz spojrzeć na następującą odpowiedź, aby użyć fetch i rzeczywistego dataURL: https://stackoverflow.com/a/50463054/599602

 21
Author: Zaptree,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-09 14:12:04

Shiv / shim / sham

Jeśli Twoje obrazy są już załadowane (lub nie), to "narzędzie"może się przydać:

Object.defineProperty
(
    HTMLImageElement.prototype,'toDataURL',
    {enumerable:false,configurable:false,writable:false,value:function(m,q)
    {
        let c=document.createElement('canvas');
        c.width=this.naturalWidth; c.height=this.naturalHeight;
        c.getContext('2d').drawImage(this,0,0); return c.toDataURL(m,q);
    }}
);

.. ale dlaczego?

Ta zaleta polega na wykorzystaniu "już załadowanych" danych obrazu, więc nie jest potrzebne dodatkowe żądanie. Dodatkowo pozwala użytkownikowi końcowemu (programiście jak ty) zdecydować CORS i/lub mime-type i quality -lub - możesz pominąć te argumenty/parametry, jak opisano w specyfikacji MDN tutaj.

Jeśli po załadowaniu tego JS (przed tym, kiedy jest to potrzebne), konwersja na dataURL jest tak prosta, jak:

Przykłady

HTML
<img src="/yo.jpg" onload="console.log(this.toDataURL('image/jpeg'))">
JS
console.log(document.getElementById("someImgID").toDataURL());

GPU fingerprinting

Jeśli martwisz się o" dokładność " bitów, możesz zmienić to narzędzie, aby dopasować je do swoich potrzeb, zgodnie z odpowiedzią @Kaiido.

 2
Author: argon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-01 01:37:03

Użyj zdarzenia onload do konwersji obrazu po załadowaniu

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
Author: Kamil Kiełczewski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-15 10:54:23

To wszystko, co musisz przeczytać.

Https://developer.mozilla.org/en-US/docs/Web/API/FileReader/readAsBinaryString

var height = 200;
var width  = 200;

canvas.width  = width;
canvas.height = height;

var ctx = canvas.getContext('2d');

ctx.strokeStyle = '#090';
ctx.beginPath();
ctx.arc(width/2, height/2, width/2 - width/10, 0, Math.PI*2);
ctx.stroke();

canvas.toBlob(function (blob) {
  //consider blob is your file object

  var reader = new FileReader();

  reader.onload = function () {
    console.log(reader.result);
  }

  reader.readAsBinaryString(blob);
});
 0
Author: ashdaily,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-16 18:01:34

W HTML5 lepiej Użyj tego:

{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}
 -3
Author: KepHec,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-01-12 10:18:20