Abdizriel
Abdizriel

Reputation: 355

Why saving canvas as jpeg or pdf result black image?

I have the following code:

var imgData;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();

imageObj.onload = function() {
    context.drawImage(imageObj, 0, 0);
};
imgData = canvas.toDataURL("image/jpeg", 1.0);
imageObj.src = 'http://images.visitcanberra.com.au/images/canberra_hero_image.jpg';

When a user click on JPG or PDF file is downloaded. There's following code for download JPG:

function saveAsJPG(){
    var pom = document.createElement('a');
    pom.setAttribute('href', imgData);
    pom.setAttribute('download', 'img.jpg');

    if (document.createEvent) {
        var event = document.createEvent('MouseEvents');
        event.initEvent('click', true, true);
        pom.dispatchEvent(event);
    } else {
        pom.click();
    }
}

And following code for PDF:

function saveAsPDF(){
          var pdf = new jsPDF();        
          pdf.addImage(imgData, 'JPEG', 0, 0);
          pdf.save("download.pdf");
      }

Code works "correct" expect issue that it don't download image but black screen. There is working JSFiddle example: https://jsfiddle.net/1c1o8wjx/

Could you help me to understand possible reasons why it's not working as supposed?

Upvotes: 1

Views: 4148

Answers (2)

markE
markE

Reputation: 105015

You are loading the balloon-city image from a domain that's different from the web page's domain. For security reasons, this "cross-domain" image drawing will cause the browsers to "taint" the canvas. Tainted canvas's are not allowed to use .toDataURL to export their content.

This "cross-domain" drawing to the canvas is why you're getting an all black file...#myCanvas has not actually created your dataURL because the browser disallowed it.

The workaround is to host your image on the same domain as your web page. Then the browser will allow canvas.toDataURL and your images will appear as they should.

Example code and a Demo:

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;

var imgData;
var img=new Image();
img.crossOrigin='anonymous';
img.onload=start;
img.src="https://dl.dropboxusercontent.com/u/139992952/multple/canberra_hero_image.jpg";
function start(){
  canvas.width=img.width;
  canvas.height=img.height;
  ctx.drawImage(img,0,0);
  imgData=canvas.toDataURL('image/jpeg',1.0);
  $('#printJPG').on('click',saveAsJPG);
}

function saveAsJPG(){
  var pom = document.createElement('a');
  pom.setAttribute('href', imgData);
  pom.setAttribute('download', 'img.jpg');

  if (document.createEvent) {
    var event = document.createEvent('MouseEvents');
    event.initEvent('click', true, true);
    pom.dispatchEvent(event);
  } else {
    pom.click();
  }
}
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<ul>
  <li><a href="#" id="printJPG">Print as JPG</a></li>
</ul>    
<canvas id="canvas" width=300 height=300></canvas>

Also note that Internet Explorer does not currently support the "download" attribute.

Upvotes: 2

Tom&#225;s Fox
Tom&#225;s Fox

Reputation: 690

You must wait for the image to load before calling canvas.toDataURL("image/jpeg", 1.0);. Try the following:

var imgData;
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var imageObj = new Image();

imageObj.onload = function() {
    context.drawImage(imageObj, 0, 0);
    imgData = canvas.toDataURL("image/jpeg", 1.0);
};
imageObj.src = 'http://images.visitcanberra.com.au/images/canberra_hero_image.jpg';

It won't work in the fiddle because of a security error (the image belongs to a different domain). Try it in your webpage.

Upvotes: 2

Related Questions