Coder Perfect

In JavaScript, how can I get the image data URL?

Problem

I have a standard HTML page with a few images (just standard HTML img /> tags). I’d like to acquire its content, preferably base64 encoded, without having to redownload the image (i.e. the image has already been loaded by the browser; now I just want the content).

That’s something I’d like to do with Greasemonkey and Firefox.

Asked by Detariael

Solution #1

Note that this only works if the image is from the same domain as the page, or if the crossOrigin=”anonymous” attribute is present, and the server supports CORS. It will also provide you a re-encoded version of the file rather than the original. See Kaiido’s response if you require the result to be identical to the original.

You will need to create a canvas element with the correct dimensions and copy the image data with the drawImage function. Then you can use the toDataURL function to get a data: url that has the base-64 encoded image. Note that the image must be fully loaded, or you’ll just get back an empty (black, transparent) image.

This is what it would look like. Because I’ve never built a Greasemonkey script, you may need to make some changes to the code to make it work in that environment.

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

Getting a JPEG-formatted image doesn’t work on older versions (around 3.5) of Firefox, so if you want to support that, you’ll need to check the compatibility. If the encoding isn’t supported, “image/png” will be used instead.

Answered by Matthew Crumley

Solution #2

This function takes a URL and returns a BASE64 image.

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”) is an example.

Answered by MuniR

Solution #3

Even though it’s a long time afterwards, none of the responses are exactly correct.

The provided picture is uncompressed and pre-multiplied when drawn on a canvas. It’s uncompressed or recompressed with a different algorithm, and it’s not multiplied when it’s exported.

All browsers and devices will have different rounding errors happening in this process (see Canvas fingerprinting).

So if one wants a base64 version of an image file, they have to request it again (most of the time it will come from cache) but this time as a Blob.

Then you may read it as an ArrayBuffer or as a dataURL using a FileReader.

Answered by Kaiido

Solution #4

Using fetch, a more current version of kaiido’s solution would be:

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: As mentioned in the comments, this will return an object url that goes to a file on your local system rather than an actual DataURL, so depending on your use case, this may not be what you require.

You can use get and an actual dataURL in the following answer: https://stackoverflow.com/a/50463054/5996

Answered by Zaptree

Solution #5

This “tool” may be useful if your image(s) are already loaded (or not):

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

This offers the advantage of leveraging “already loaded” image data, requiring no further requests. Furthermore, it allows the end-user (you, the programmer) to choose the CORS and/or mime-type and quality -OR- you can leave these arguments/parameters out, as mentioned in the MDN specification here.

If you already have this JS loaded (before you need it), changing to dataURL is as simple as:

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

If the “preciseness” of the bits is an issue, you can modify this tool to meet your needs, as @Kaiido’s answer suggests.

Answered by argon

Post is based on https://stackoverflow.com/questions/934012/get-image-data-url-in-javascript