1

I am trying to get an image to automatically download after it has been created. I have this so far:

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var img1 = loadImage('https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png', main);

var img2 = loadImage('http://introcs.cs.princeton.edu/java/31datatype/peppers.jpg', main);
var imagesLoaded = 0;
function main() {
    imagesLoaded += 1;

    if(imagesLoaded == 2) {
        // composite now
        ctx.drawImage(img1, 0, 0);
        
        ctx.globalAlpha = 0.5;
        ctx.drawImage(img2, 0, 0);
        
        document.location.href = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
    }
}

function loadImage(src, onload) {
    // http://www.thefutureoftheweb.com/blog/image-onload-isnt-being-called
    var img = new Image();
    
    img.onload = onload;
    img.src = src;

    return img;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas width="512" height="512" id="canvas"></canvas>

The image is processed and created correctly but the download is not triggered and the following error message is displayed:

Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported

I have read up on the MDN doc on CORS enabled image and have tried to set the crossOrigin to anonymous but that still doesn't work.

Is there a better method to use to trigger the download?

1 Answer 1

1

You need to set image crossOrigin property before setting src.

Since you don't have access to the server the resources are on to set the Access-Control-Allow-Origin response headers, you're going to need a proxy.

I'm using https://cors.io for this answer but if you can use whichever does it for you.

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

var img1 = loadImage('https://cors.io/?https://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png', main);


var img2 = loadImage('https://cors.io/?http://introcs.cs.princeton.edu/java/31datatype/peppers.jpg', main);
var imagesLoaded = 0;

function main() {
  imagesLoaded += 1;

  if (imagesLoaded == 2) {
    // composite now
    ctx.drawImage(img1, 0, 0);

    ctx.globalAlpha = 0.5;
    ctx.drawImage(img2, 0, 0);

    document.location.href = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
  }
}

function loadImage(src, onload) {
  // http://www.thefutureoftheweb.com/blog/image-onload-isnt-being-called
  var img = new Image();

  img.onload = onload;
  img.crossOrigin = 'anonymous';
  img.src = src;

  return img;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas width="512" height="512" id="canvas"></canvas>

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for the answer but using a third part proxy site is great for dev, not so great for production
You can easily setup a backend to fetch the resource for yourself. I do have a thought though on using fetch to get the image resource, making a base64 blob of it and using that to set img.src to data:image/gif;base64,.... That may just work.

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.