28

Using JavaScript, I want to convert an img tag like this:

<img width="11" height="14" src="http://mysite/file.gif" alt="File Icon">

Into one with a dataurl like this:

<img width="11" height="14" src="data:image/gif;base64,R0lGODlhCwAOAMQfAP////7+/vj4+Hh4eHd3d/v7+/Dw8HV1dfLy8ubm5vX19e3t7fr6+nl5edra2nZ2dnx8fMHBwYODg/b29np6eujo6JGRkeHh4eTk5LCwsN3d3dfX13Jycp2dnevr6////yH5BAEAAB8ALAAAAAALAA4AAAVq4NFw1DNAX/o9imAsBtKpxKRd1+YEWUoIiUoiEWEAApIDMLGoRCyWiKThenkwDgeGMiggDLEXQkDoThCKNLpQDgjeAsY7MHgECgx8YR8oHwNHfwADBACGh4EDA4iGAYAEBAcQIg0Dk gcEIQA7" alt="File Icon">

Is this possible?

5
  • 1
    possible duplicate of Convert image to base64 with javascript Commented Sep 5, 2014 at 16:59
  • 1
    Because jsPDF only seems to support images like that. Commented Sep 5, 2014 at 17:00
  • 4
    I don't think it's a duplicate of that answer because he's downloading the binary data from the server and converting it to Base64. I'm trying to convert an absolute url to base64 on the client without downloading it a second time if possible. Commented Sep 5, 2014 at 17:05
  • @adam0101 But you have to download it once to convert the data. Then it wont be downloaded again with the base64 string. using base64 images prevents from downloading the images. Commented Sep 5, 2014 at 17:13
  • 1
    @RomainBraun, still, that question and answer converts a string to Base64. I don't have a string to convert, only a url. The btoa() function doesn't accept a url. Commented Sep 5, 2014 at 17:21

4 Answers 4

46

Here's how to get the data url of an image with fetch:

let blob = await fetch("https://example.com/image.png")
    .then(r => r.blob());

let dataUrl = await new Promise(resolve => {
    let reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.readAsDataURL(blob);
});
Sign up to request clarification or add additional context in comments.

3 Comments

This comes back as a data:text/html I am trying to get data:image/png
Then replace the text/html with image/png in your string.
Note that the example URL serves a web page rather than an image, so that is likely the problem rather than the code itself. @S.Stark
21

First, load the image into a canvas

var canvas = document.createElement("canvas");
context = canvas.getContext('2d');

make_base();

function make_base()
{
  base_image = new Image();
  base_image.src = 'img/base.png';
  base_image.onload = function(){
    context.drawImage(base_image, 100, 100);
  }
}

Make sure to update the context.drawImage(base_image, 100, 100); to values appropriate for your application.

Source: https://stackoverflow.com/a/6011402/3969707

Then convert the canvas to data.

var jpegUrl = canvas.toDataURL("image/jpeg");
var pngUrl = canvas.toDataURL(); // PNG is the default

Source: https://stackoverflow.com/a/15685877/3969707

1 Comment

Thanks! This worked great, but it turns out that if I include html2canvas with jsPDF it takes care of converting the images for me!
9

I'd solve this problem with a temporary canvas element with the same size of the image loaded:

function imageToUri(url, callback) {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    var base_image = new Image();
    base_image.src = url;
    base_image.onload = function() {
        canvas.width = base_image.width;
        canvas.height = base_image.height;

        ctx.drawImage(base_image, 0, 0);
    
        callback(canvas.toDataURL('image/png'));

        canvas.remove();
    }
}

imageToUri('./assets/some_image.png', function(uri) {
    console.log(uri);
});

2 Comments

Thank you for submitting actually reusable code. Most people don't and it bugs me
No problem, I try to make the same way I wish to get.
1

This really isn't something you may want to do in JavaScript as it requires the image be parsed in JavaScript which is very slow. You would be loading the image and then putting the output of the function into the img tag, which doesn't save bandwidth, decrease complexity, or improve security.

Your best bet is to do this server-side. I've used this to great success in the past for generating pages which need to have absolutely no linked/referenced external resources. You can, for jsPDF, then use raw JavaScript or jQuery to get the data of an image to pass into the PDF creation process.

This will work everywhere and not rely on resorting to canvas which doesn't have full mobile browser support.

2 Comments

What if I stored that data on local storage? First I download the image, then I store it in users' local storage. Then users can load that image from their local storage. If the image is already downloaded, then the user can skip the downloading part which might increase the performance. Is this okay?
Browser caching handles this fairly well so you shouldn't in most applications need to store an image in local storage in most projects. If this is something that you're really looking to do there is another SO question that covers this pretty well. It uses canvas but that's available in all modern web browsers now: - stackoverflow.com/questions/19183180/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.