Получить URL-адрес данных изображения в JavaScript? - PullRequest
320 голосов
/ 01 июня 2009

У меня есть обычная HTML-страница с некоторыми изображениями (только обычные <img /> HTML-теги). Я хотел бы получить их содержимое, желательно в кодировке base64, без необходимости повторной загрузки изображения (т. Е. Оно уже загружено браузером, поэтому теперь я хочу содержимое).

Я бы хотел добиться этого с Greasemonkey и Firefox.

Ответы [ 8 ]

389 голосов
/ 01 июня 2009

Примечание: Это работает, только если изображение находится в том же домене, что и страница, или имеет атрибут crossOrigin="anonymous" и сервер поддерживает CORS. Это также не даст вам оригинальный файл, а перекодированную версию. Если вам нужно, чтобы результат был идентичен оригиналу, см. ответ Кайидо .


Вам потребуется создать элемент canvas с правильными размерами и скопировать данные изображения с помощью функции drawImage. Затем вы можете использовать функцию toDataURL для получения data: url с закодированным изображением base-64. Обратите внимание, что изображение должно быть полностью загружено, иначе вы просто получите пустое (черное, прозрачное) изображение.

Это было бы что-то вроде этого. Я никогда не писал сценарий Greasemonkey, поэтому вам может потребоваться настроить код для работы в этой среде.

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,/, "");
}

Получение изображения в формате JPEG не работает на более старых версиях (около 3.5) Firefox, поэтому, если вы хотите это поддерживать, вам нужно проверить совместимость. Если кодировка не поддерживается, по умолчанию будет использоваться «image / png».

71 голосов
/ 15 мая 2013

Эта функция берет URL, затем возвращает изображение 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;
}

Назовите это так: getBase64FromImageUrl("images/slbltxt.png")

42 голосов
/ 21 марта 2017

Придет много позже, но ни один из ответов здесь не является полностью правильным.

При рисовании на холсте переданное изображение не сжимается + все предварительно умножается.
При экспорте он распаковывается или сжимается по другому алгоритму и не умножается.

Все браузеры и устройства будут иметь разные ошибки округления, происходящие в этом процессе
(см. Отпечатки холста ).

Так что, если кто-то хочет версию изображения для base64, он должен запросить его снова (большую часть времени он будет поступать из кэша), но на этот раз как Blob.

Затем вы можете использовать FileReader , чтобы прочитать его как ArrayBuffer или как 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">
23 голосов
/ 11 июня 2014

В дополнение к ответу Мэтью я хотел бы сказать, что image.width и image.height возвращают отображаемый размер изображения (и обрезают изображение при его рисовании на холсте)

Вместо этого используйте naturalWidth и naturalHeight, в которых используется изображение в реальном размере.

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

15 голосов
/ 22 июля 2017

Более современная версия ответа Кайидо с использованием fetch будет:

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

1 голос
/ 24 апреля 2019

Использование события onload для преобразования изображения после загрузки

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; }
image

0 голосов
/ 12 января 2019

В HTML5 лучше использовать это:

{
//...
canvas.width = img.naturalWidth; //img.width;
canvas.height = img.naturalHeight; //img.height;
//...
}
0 голосов
/ 15 декабря 2017

function encodeImageFileAsURL(cb) {
    return function() {
        var file = this.files[0];
        var reader = new FileReader();
        reader.onloadend = function() {
            cb(reader.result);
        }
        reader.readAsDataURL(file);
    }
}

$('#inputFileToLoad').change(encodeImageFileAsURL(function(base64Img) {
    $('.output')
        .find('textarea')
        .val(base64Img)
        .end()
        .find('a')
        .attr('href', base64Img)
        .text(base64Img)
        .end()
        .find('img')
        .attr('src', base64Img);
}));
@import url('//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css'); body{ padding: 20px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h2>Input</h2>
<form class="input-group" id="img2b64">
    <input id="inputFileToLoad" type="file" onchange="encodeImageFileAsURL();" />
</form>
<hr>
Вот пример рабочей скрипки: - загрузить и получить данные изображения
...